<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Interactive BOM for KiCAD</title>
  <style type="text/css">
:root {
  --pcb-edge-color: black;
  --pad-color: #878787;
  --pad-color-highlight: #D04040;
  --pin1-outline-color: #ffb629;
  --pin1-outline-color-highlight: #b4ff03;
  --silkscreen-edge-color: #aa4;
  --silkscreen-polygon-color: #4aa;
  --silkscreen-text-color: #4aa;
  --fabrication-edge-color: #907651;
  --fabrication-polygon-color: #907651;
  --fabrication-text-color: #a27c24;
  --track-color: #def5f1;
  --track-color-highlight: #D04040;
  --zone-color: #def5f1;
  --zone-color-highlight: #d0404080;
}

html, body {
  margin: 0px;
  height: 100%;
  font-family: Verdana, sans-serif;
}

.dark.topmostdiv {
  --pcb-edge-color: #eee;
  --pad-color: #808080;
  --pin1-outline-color: #ffa800;
  --pin1-outline-color-highlight: #ccff00;
  --track-color: #42524f;
  --zone-color: #42524f;
  background-color: #252c30;
  color: #eee;
}

button {
  background-color: #eee;
  border: 1px solid #888;
  color: black;
  height: 44px;
  width: 44px;
  text-align: center;
  text-decoration: none;
  display: inline-block;
  font-size: 14px;
  font-weight: bolder;
}

.dark button {
  /* This will be inverted */
  background-color: #c3b7b5;
}

button.depressed {
  background-color: #0a0;
  color: white;
}

.dark button.depressed {
  /* This will be inverted */
  background-color: #b3b;
}

button:focus {
  outline: 0;
}

button#tb-btn {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8.47 8.47'%3E%3Crect transform='translate(0 -288.53)' ry='1.17' y='288.8' x='.27' height='7.94' width='7.94' fill='%23f9f9f9'/%3E%3Cg transform='translate(0 -288.53)'%3E%3Crect width='7.94' height='7.94' x='.27' y='288.8' ry='1.17' fill='none' stroke='%23000' stroke-width='.4' stroke-linejoin='round'/%3E%3Cpath d='M1.32 290.12h5.82M1.32 291.45h5.82' fill='none' stroke='%23000' stroke-width='.4'/%3E%3Cpath d='M4.37 292.5v4.23M.26 292.63H8.2' fill='none' stroke='%23000' stroke-width='.3'/%3E%3Ctext font-weight='700' font-size='3.17' font-family='sans-serif'%3E%3Ctspan x='1.35' y='295.73'%3EF%3C/tspan%3E%3Ctspan x='5.03' y='295.68'%3EB%3C/tspan%3E%3C/text%3E%3C/g%3E%3C/svg%3E%0A");
}

button#lr-btn {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8.47 8.47'%3E%3Crect transform='translate(0 -288.53)' ry='1.17' y='288.8' x='.27' height='7.94' width='7.94' fill='%23f9f9f9'/%3E%3Cg transform='translate(0 -288.53)'%3E%3Crect width='7.94' height='7.94' x='.27' y='288.8' ry='1.17' fill='none' stroke='%23000' stroke-width='.4' stroke-linejoin='round'/%3E%3Cpath d='M1.06 290.12H3.7m-2.64 1.33H3.7m-2.64 1.32H3.7m-2.64 1.3H3.7m-2.64 1.33H3.7' fill='none' stroke='%23000' stroke-width='.4'/%3E%3Cpath d='M4.37 288.8v7.94m0-4.11h3.96' fill='none' stroke='%23000' stroke-width='.3'/%3E%3Ctext font-weight='700' font-size='3.17' font-family='sans-serif'%3E%3Ctspan x='5.11' y='291.96'%3EF%3C/tspan%3E%3Ctspan x='5.03' y='295.68'%3EB%3C/tspan%3E%3C/text%3E%3C/g%3E%3C/svg%3E%0A");
}

button#bom-btn {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8.47 8.47'%3E%3Crect transform='translate(0 -288.53)' ry='1.17' y='288.8' x='.27' height='7.94' width='7.94' fill='%23f9f9f9'/%3E%3Cg transform='translate(0 -288.53)' fill='none' stroke='%23000' stroke-width='.4'%3E%3Crect width='7.94' height='7.94' x='.27' y='288.8' ry='1.17' stroke-linejoin='round'/%3E%3Cpath d='M1.59 290.12h5.29M1.59 291.45h5.33M1.59 292.75h5.33M1.59 294.09h5.33M1.59 295.41h5.33'/%3E%3C/g%3E%3C/svg%3E");
}

button#bom-grouped-btn {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32'%3E%3Cg stroke='%23000' stroke-linejoin='round' class='layer'%3E%3Crect width='29' height='29' x='1.5' y='1.5' stroke-width='2' fill='%23fff' rx='5' ry='5'/%3E%3Cpath stroke-linecap='square' stroke-width='2' d='M6 10h4m4 0h5m4 0h3M6.1 22h3m3.9 0h5m4 0h4m-16-8h4m4 0h4'/%3E%3Cpath stroke-linecap='null' d='M5 17.5h22M5 26.6h22M5 5.5h22'/%3E%3C/g%3E%3C/svg%3E");
}

button#bom-ungrouped-btn {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32'%3E%3Cg stroke='%23000' stroke-linejoin='round' class='layer'%3E%3Crect width='29' height='29' x='1.5' y='1.5' stroke-width='2' fill='%23fff' rx='5' ry='5'/%3E%3Cpath stroke-linecap='square' stroke-width='2' d='M6 10h4m-4 8h3m-3 8h4'/%3E%3Cpath stroke-linecap='null' d='M5 13.5h22m-22 8h22M5 5.5h22'/%3E%3C/g%3E%3C/svg%3E");
}

button#bom-netlist-btn {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32'%3E%3Cg fill='none' stroke='%23000' class='layer'%3E%3Crect width='29' height='29' x='1.5' y='1.5' stroke-width='2' fill='%23fff' rx='5' ry='5'/%3E%3Cpath stroke-width='2' d='M6 26l6-6v-8m13.8-6.3l-6 6v8'/%3E%3Ccircle cx='11.8' cy='9.5' r='2.8' stroke-width='2'/%3E%3Ccircle cx='19.8' cy='22.8' r='2.8' stroke-width='2'/%3E%3C/g%3E%3C/svg%3E");
}

button#copy {
  background-image: url("data:image/svg+xml,%3Csvg height='48' viewBox='0 0 48 48' width='48' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 0h48v48h-48z' fill='none'/%3E%3Cpath d='M32 2h-24c-2.21 0-4 1.79-4 4v28h4v-28h24v-4zm6 8h-22c-2.21 0-4 1.79-4 4v28c0 2.21 1.79 4 4 4h22c2.21 0 4-1.79 4-4v-28c0-2.21-1.79-4-4-4zm0 32h-22v-28h22v28z'/%3E%3C/svg%3E");
  background-position: 6px 6px;
  background-repeat: no-repeat;
  background-size: 26px 26px;
  border-radius: 6px;
  height: 40px;
  width: 40px;
  margin: 10px 5px;
}

button#copy:active {
    box-shadow: inset 0px 0px 5px #6c6c6c;
}

textarea.clipboard-temp {
  position: fixed;
  top: 0;
  left: 0;
  width: 2em;
  height: 2em;
  padding: 0;
  border: None;
  outline: None;
  box-shadow: None;
  background: transparent;
}

.left-most-button {
  border-right: 0;
  border-top-left-radius: 6px;
  border-bottom-left-radius: 6px;
}

.middle-button {
  border-right: 0;
}

.right-most-button {
  border-top-right-radius: 6px;
  border-bottom-right-radius: 6px;
}

.button-container {
  font-size: 0;
  margin: 10px 10px 10px 0px;
}

.dark .button-container {
  filter: invert(1);
}

.button-container button {
  background-size: 32px 32px;
  background-position: 5px 5px;
  background-repeat: no-repeat;
}

@media print {
  .hideonprint {
    display: none;
  }
}

canvas {
  cursor: crosshair;
}

canvas:active {
  cursor: grabbing;
}

.fileinfo {
  width: 100%;
  max-width: 1000px;
  border: none;
  padding: 5px;
}

.fileinfo .title {
  font-size: 20pt;
  font-weight: bold;
}

.fileinfo td {
  overflow: hidden;
  white-space: nowrap;
  max-width: 1px;
  width: 50%;
  text-overflow: ellipsis;
}

.bom {
  border-collapse: collapse;
  font-family: Consolas, "DejaVu Sans Mono", Monaco, monospace;
  font-size: 10pt;
  table-layout: fixed;
  width: 100%;
  margin-top: 1px;
}

.bom th, .bom td {
  border: 1px solid black;
  padding: 5px;
  word-wrap: break-word;
  text-align: center;
  position: relative;
}

.dark .bom th, .dark .bom td {
  border: 1px solid #777;
}

.bom th {
  background-color: #CCCCCC;
  background-clip: padding-box;
}

.dark .bom th {
  background-color: #3b4749;
}

.bom tr.highlighted:nth-child(n) {
  background-color: #cfc;
}

.dark .bom tr.highlighted:nth-child(n) {
  background-color: #226022;
}

.bom tr:nth-child(even) {
  background-color: #f2f2f2;
}

.dark .bom tr:nth-child(even) {
  background-color: #313b40;
}

.bom tr.checked {
  color: #aaa;
}

.dark .bom tr.checked {
  color: #666;
}

.bom tr {
  transition: background-color 0.2s;
}

.bom .numCol {
  width: 25px;
}

.bom .Description {
  width: 10%;
}

.bom .Part {
  width: 10%;
}

.bom .Value {
  width: 15%;
}

.bom .Quantity {
  width: 65px;
}

.bom th .sortmark {
  position: absolute;
  right: 1px;
  top: 1px;
  margin-top: -5px;
  border-width: 5px;
  border-style: solid;
  border-color: transparent transparent #221 transparent;
  transform-origin: 50% 85%;
  transition: opacity 0.2s, transform 0.4s;
}

.dark .bom th .sortmark {
  filter: invert(1);
}

.bom th .sortmark.none {
  opacity: 0;
}

.bom th .sortmark.desc {
  transform: rotate(180deg);
}

.bom th:hover .sortmark.none {
  opacity: 0.5;
}

.bom .bom-checkbox {
  width: 30px;
  position: relative;
  user-select: none;
  -moz-user-select: none;
}

.bom .bom-checkbox:before {
  content: "";
  position: absolute;
  border-width: 15px;
  border-style: solid;
  border-color: #51829f transparent transparent transparent;
  visibility: hidden;
  top: -15px;
}

.bom .bom-checkbox:after {
  content: "Double click to set/unset all";
  position: absolute;
  color: white;
  top: -35px;
  left: -26px;
  background: #51829f;
  padding: 5px 15px;
  border-radius: 8px;
  white-space: nowrap;
  visibility: hidden;
}

.bom .bom-checkbox:hover:before, .bom .bom-checkbox:hover:after {
  visibility: visible;
  transition: visibility 0.2s linear 1s;
}

.split {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  overflow-y: auto;
  overflow-x: hidden;
  background-color: inherit;
}

.split.split-horizontal, .gutter.gutter-horizontal {
  height: 100%;
  float: left;
}

.gutter {
  background-color: #ddd;
  background-repeat: no-repeat;
  background-position: 50%;
  transition: background-color 0.3s;
}

.dark .gutter {
  background-color: #777;
}

.gutter.gutter-horizontal {
  background-image: url('');
  cursor: ew-resize;
  width: 5px;
}

.gutter.gutter-vertical {
  background-image: url('');
  cursor: ns-resize;
  height: 5px;
}

.searchbox {
  float: left;
  height: 40px;
  margin: 10px 5px;
  padding: 12px 32px;
  font-family: Consolas, "DejaVu Sans Mono", Monaco, monospace;
  font-size: 18px;
  box-sizing: border-box;
  border: 1px solid #888;
  border-radius: 6px;
  outline: none;
  background-color: #eee;
  transition: background-color 0.2s, border 0.2s;
  background-image: url('');
  background-position: 10px 10px;
  background-repeat: no-repeat;
}

.dark .searchbox {
  background-color: #111;
  color: #eee;
}

.searchbox::placeholder {
  color: #ccc;
}

.dark .searchbox::placeholder {
  color: #666;
}

.filter {
  width: calc(60% - 64px);
}

.reflookup {
  width: calc(40% - 10px);
}

input[type=text]:focus {
  background-color: white;
  border: 1px solid #333;
}

.dark input[type=text]:focus {
  background-color: #333;
  border: 1px solid #ccc;
}

mark.highlight {
  background-color: #5050ff;
  color: #fff;
  padding: 2px;
  border-radius: 6px;
}

.dark mark.highlight {
  background-color: #76a6da;
  color: #111;
}

.menubtn {
  background-color: white;
  border: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='36' height='36' viewBox='0 0 20 20'%3E%3Cpath fill='none' d='M0 0h20v20H0V0z'/%3E%3Cpath d='M15.95 10.78c.03-.25.05-.51.05-.78s-.02-.53-.06-.78l1.69-1.32c.15-.12.19-.34.1-.51l-1.6-2.77c-.1-.18-.31-.24-.49-.18l-1.99.8c-.42-.32-.86-.58-1.35-.78L12 2.34c-.03-.2-.2-.34-.4-.34H8.4c-.2 0-.36.14-.39.34l-.3 2.12c-.49.2-.94.47-1.35.78l-1.99-.8c-.18-.07-.39 0-.49.18l-1.6 2.77c-.1.18-.06.39.1.51l1.69 1.32c-.04.25-.07.52-.07.78s.02.53.06.78L2.37 12.1c-.15.12-.19.34-.1.51l1.6 2.77c.1.18.31.24.49.18l1.99-.8c.42.32.86.58 1.35.78l.3 2.12c.04.2.2.34.4.34h3.2c.2 0 .37-.14.39-.34l.3-2.12c.49-.2.94-.47 1.35-.78l1.99.8c.18.07.39 0 .49-.18l1.6-2.77c.1-.18.06-.39-.1-.51l-1.67-1.32zM10 13c-1.65 0-3-1.35-3-3s1.35-3 3-3 3 1.35 3 3-1.35 3-3 3z'/%3E%3C/svg%3E%0A");
  background-position: center;
  background-repeat: no-repeat;
}

.statsbtn {
  background-color: white;
  border: none;
  background-image: url("data:image/svg+xml,%3Csvg width='36' height='36' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4 6h28v24H4V6zm0 8h28v8H4m9-16v24h10V5.8' fill='none' stroke='%23000' stroke-width='2'/%3E%3C/svg%3E");
  background-position: center;
  background-repeat: no-repeat;
}

.iobtn {
  background-color: white;
  border: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='36' height='36'%3E%3Cpath fill='none' stroke='%23000' stroke-width='2' d='M3 33v-7l6.8-7h16.5l6.7 7v7H3zM3.2 26H33M21 9l5-5.9 5 6h-2.5V15h-5V9H21zm-4.9 0l-5 6-5-6h2.5V3h5v6h2.5z'/%3E%3Cpath fill='none' stroke='%23000' d='M6.1 29.5H10'/%3E%3C/svg%3E");
  background-position: center;
  background-repeat: no-repeat;
}

.dark .statsbtn, .dark .savebtn, .dark .menubtn, .dark .iobtn {
  filter: invert(1);
}

.flexbox {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
}

.savebtn {
  background-color: #d6d6d6;
  width: auto;
  height: 30px;
  flex-grow: 1;
  margin: 5px;
  border-radius: 4px;
}

.savebtn:active {
  background-color: #0a0;
  color: white;
}

.dark .savebtn:active {
  /* This will be inverted */
  background-color: #b3b;
}

.stats {
  border-collapse: collapse;
  font-size: 12pt;
  table-layout: fixed;
  width: 100%;
  min-width: 450px;
}

.dark .stats td {
  border: 1px solid #bbb;
}

.stats td {
  border: 1px solid black;
  padding: 5px;
  word-wrap: break-word;
  text-align: center;
  position: relative;
}

#checkbox-stats div {
  position: absolute;
  left: 0;
  top: 0;
  height: 100%;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

#checkbox-stats .bar {
  background-color: rgba(28, 251, 0, 0.6);
}

.menu {
  position: relative;
  display: inline-block;
  margin: 10px 10px 10px 0px;
}

.menu-content {
  display: none;
  position: absolute;
  background-color: white;
  right: 0;
  min-width: 300px;
  box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
  z-index: 100;
  padding: 8px;
}

.dark .menu-content {
  background-color: #111;
}

.menu:hover .menu-content {
  display: block;
}

.menu:hover .menubtn, .menu:hover .iobtn, .menu:hover .statsbtn {
  background-color: #eee;
}

.menu-label {
  display: inline-block;
  padding: 8px;
  border: 1px solid #ccc;
  border-top: 0;
  width: calc(100% - 18px);
}

.menu-label-top {
  border-top: 1px solid #ccc;
}

.menu-textbox {
  float: left;
  height: 24px;
  margin: 10px 5px;
  padding: 5px 5px;
  font-family: Consolas, "DejaVu Sans Mono", Monaco, monospace;
  font-size: 14px;
  box-sizing: border-box;
  border: 1px solid #888;
  border-radius: 4px;
  outline: none;
  background-color: #eee;
  transition: background-color 0.2s, border 0.2s;
  width: calc(100% - 10px);
}

.menu-textbox.invalid, .dark .menu-textbox.invalid {
  color: red;
}

.dark .menu-textbox {
  background-color: #222;
  color: #eee;
}

.radio-container {
  margin: 4px;
}

.topmostdiv {
  width: 100%;
  height: 100%;
  background-color: white;
  transition: background-color 0.3s;
}

#top {
  height: 78px;
  border-bottom: 2px solid black;
}

.dark #top {
  border-bottom: 2px solid #ccc;
}

#dbg {
  display: block;
}

::-webkit-scrollbar {
  width: 8px;
}

::-webkit-scrollbar-track {
  background: #aaa;
}

::-webkit-scrollbar-thumb {
  background: #666;
  border-radius: 3px;
}

::-webkit-scrollbar-thumb:hover {
  background: #555;
}

.slider {
  -webkit-appearance: none;
  width: 100%;
  margin: 3px 0;
  padding: 0;
  outline: none;
  opacity: 0.7;
  -webkit-transition: .2s;
  transition: opacity .2s;
  border-radius: 3px;
}

.slider:hover {
  opacity: 1;
}

.slider:focus {
  outline: none;
}

.slider::-webkit-slider-runnable-track {
  -webkit-appearance: none;
  width: 100%;
  height: 8px;
  background: #d3d3d3;
  border-radius: 3px;
  border: none;
}

.slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: #0a0;
  cursor: pointer;
  margin-top: -4px;
}

.dark .slider::-webkit-slider-thumb {
  background: #3d3;
}

.slider::-moz-range-thumb {
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: #0a0;
  cursor: pointer;
}

.slider::-moz-range-track {
  height: 8px;
  background: #d3d3d3;
  border-radius: 3px;
}

.dark .slider::-moz-range-thumb {
  background: #3d3;
}

.slider::-ms-track {
  width: 100%;
  height: 8px;
  border-width: 3px 0;
  background: transparent;
  border-color: transparent;
  color: transparent;
  transition: opacity .2s;
}

.slider::-ms-fill-lower {
  background: #d3d3d3;
  border: none;
  border-radius: 3px;
}

.slider::-ms-fill-upper {
  background: #d3d3d3;
  border: none;
  border-radius: 3px;
}

.slider::-ms-thumb {
  width: 15px;
  height: 15px;
  border-radius: 50%;
  background: #0a0;
  cursor: pointer;
  margin: 0;
}

.shameless-plug {
  font-size: 0.8em;
  text-align: center;
  display: block;
}

a {
  color: #0278a4;
}

.dark a {
  color: #00b9fd;
}

#frontcanvas, #backcanvas {
    touch-action: none;
}


  </style>
  <script type="text/javascript" >
///////////////////////////////////////////////
/*
  Split.js - v1.3.5
  MIT License
  https://github.com/nathancahill/Split.js
*/
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.Split=t()}(this,function(){"use strict";var e=window,t=e.document,n="addEventListener",i="removeEventListener",r="getBoundingClientRect",s=function(){return!1},o=e.attachEvent&&!e[n],a=["","-webkit-","-moz-","-o-"].filter(function(e){var n=t.createElement("div");return n.style.cssText="width:"+e+"calc(9px)",!!n.style.length}).shift()+"calc",l=function(e){return"string"==typeof e||e instanceof String?t.querySelector(e):e};return function(u,c){function z(e,t,n){var i=A(y,t,n);Object.keys(i).forEach(function(t){return e.style[t]=i[t]})}function h(e,t){var n=B(y,t);Object.keys(n).forEach(function(t){return e.style[t]=n[t]})}function f(e){var t=E[this.a],n=E[this.b],i=t.size+n.size;t.size=e/this.size*i,n.size=i-e/this.size*i,z(t.element,t.size,this.aGutterSize),z(n.element,n.size,this.bGutterSize)}function m(e){var t;this.dragging&&((t="touches"in e?e.touches[0][b]-this.start:e[b]-this.start)<=E[this.a].minSize+M+this.aGutterSize?t=E[this.a].minSize+this.aGutterSize:t>=this.size-(E[this.b].minSize+M+this.bGutterSize)&&(t=this.size-(E[this.b].minSize+this.bGutterSize)),f.call(this,t),c.onDrag&&c.onDrag())}function g(){var e=E[this.a].element,t=E[this.b].element;this.size=e[r]()[y]+t[r]()[y]+this.aGutterSize+this.bGutterSize,this.start=e[r]()[G]}function d(){var t=this,n=E[t.a].element,r=E[t.b].element;t.dragging&&c.onDragEnd&&c.onDragEnd(),t.dragging=!1,e[i]("mouseup",t.stop),e[i]("touchend",t.stop),e[i]("touchcancel",t.stop),t.parent[i]("mousemove",t.move),t.parent[i]("touchmove",t.move),delete t.stop,delete t.move,n[i]("selectstart",s),n[i]("dragstart",s),r[i]("selectstart",s),r[i]("dragstart",s),n.style.userSelect="",n.style.webkitUserSelect="",n.style.MozUserSelect="",n.style.pointerEvents="",r.style.userSelect="",r.style.webkitUserSelect="",r.style.MozUserSelect="",r.style.pointerEvents="",t.gutter.style.cursor="",t.parent.style.cursor=""}function S(t){var i=this,r=E[i.a].element,o=E[i.b].element;!i.dragging&&c.onDragStart&&c.onDragStart(),t.preventDefault(),i.dragging=!0,i.move=m.bind(i),i.stop=d.bind(i),e[n]("mouseup",i.stop),e[n]("touchend",i.stop),e[n]("touchcancel",i.stop),i.parent[n]("mousemove",i.move),i.parent[n]("touchmove",i.move),r[n]("selectstart",s),r[n]("dragstart",s),o[n]("selectstart",s),o[n]("dragstart",s),r.style.userSelect="none",r.style.webkitUserSelect="none",r.style.MozUserSelect="none",r.style.pointerEvents="none",o.style.userSelect="none",o.style.webkitUserSelect="none",o.style.MozUserSelect="none",o.style.pointerEvents="none",i.gutter.style.cursor=j,i.parent.style.cursor=j,g.call(i)}function v(e){e.forEach(function(t,n){if(n>0){var i=F[n-1],r=E[i.a],s=E[i.b];r.size=e[n-1],s.size=t,z(r.element,r.size,i.aGutterSize),z(s.element,s.size,i.bGutterSize)}})}function p(){F.forEach(function(e){e.parent.removeChild(e.gutter),E[e.a].element.style[y]="",E[e.b].element.style[y]=""})}void 0===c&&(c={});var y,b,G,E,w=l(u[0]).parentNode,D=e.getComputedStyle(w).flexDirection,U=c.sizes||u.map(function(){return 100/u.length}),k=void 0!==c.minSize?c.minSize:100,x=Array.isArray(k)?k:u.map(function(){return k}),L=void 0!==c.gutterSize?c.gutterSize:10,M=void 0!==c.snapOffset?c.snapOffset:30,O=c.direction||"horizontal",j=c.cursor||("horizontal"===O?"ew-resize":"ns-resize"),C=c.gutter||function(e,n){var i=t.createElement("div");return i.className="gutter gutter-"+n,i},A=c.elementStyle||function(e,t,n){var i={};return"string"==typeof t||t instanceof String?i[e]=t:i[e]=o?t+"%":a+"("+t+"% - "+n+"px)",i},B=c.gutterStyle||function(e,t){return n={},n[e]=t+"px",n;var n};"horizontal"===O?(y="width","clientWidth",b="clientX",G="left","paddingLeft"):"vertical"===O&&(y="height","clientHeight",b="clientY",G="top","paddingTop");var F=[];return E=u.map(function(e,t){var i,s={element:l(e),size:U[t],minSize:x[t]};if(t>0&&(i={a:t-1,b:t,dragging:!1,isFirst:1===t,isLast:t===u.length-1,direction:O,parent:w},i.aGutterSize=L,i.bGutterSize=L,i.isFirst&&(i.aGutterSize=L/2),i.isLast&&(i.bGutterSize=L/2),"row-reverse"===D||"column-reverse"===D)){var a=i.a;i.a=i.b,i.b=a}if(!o&&t>0){var c=C(t,O);h(c,L),c[n]("mousedown",S.bind(i)),c[n]("touchstart",S.bind(i)),w.insertBefore(c,s.element),i.gutter=c}0===t||t===u.length-1?z(s.element,s.size,L/2):z(s.element,s.size,L);var f=s.element[r]()[y];return f<s.minSize&&(s.minSize=f),t>0&&F.push(i),s}),o?{setSizes:v,destroy:p}:{setSizes:v,getSizes:function(){return E.map(function(e){return e.size})},collapse:function(e){if(e===F.length){var t=F[e-1];g.call(t),o||f.call(t,t.size-t.bGutterSize)}else{var n=F[e];g.call(n),o||f.call(n,n.aGutterSize)}},destroy:p}}});

///////////////////////////////////////////////

///////////////////////////////////////////////
// Copyright (c) 2013 Pieroxy <pieroxy@pieroxy.net>
// This work is free. You can redistribute it and/or modify it
// under the terms of the WTFPL, Version 2
// For more information see LICENSE.txt or http://www.wtfpl.net/
//
// For more information, the home page:
// http://pieroxy.net/blog/pages/lz-string/testing.html
//
// LZ-based compression algorithm, version 1.4.4
var LZString=function(){var o=String.fromCharCode,i={};var n={decompressFromBase64:function(o){return null==o?"":""==o?null:n._decompress(o.length,32,function(n){return function(o,n){if(!i[o]){i[o]={};for(var t=0;t<o.length;t++)i[o][o.charAt(t)]=t}return i[o][n]}("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",o.charAt(n))})},_decompress:function(i,n,t){var r,e,a,s,p,u,l,f=[],c=4,d=4,h=3,v="",g=[],m={val:t(0),position:n,index:1};for(r=0;r<3;r+=1)f[r]=r;for(a=0,p=Math.pow(2,2),u=1;u!=p;)s=m.val&m.position,m.position>>=1,0==m.position&&(m.position=n,m.val=t(m.index++)),a|=(s>0?1:0)*u,u<<=1;switch(a){case 0:for(a=0,p=Math.pow(2,8),u=1;u!=p;)s=m.val&m.position,m.position>>=1,0==m.position&&(m.position=n,m.val=t(m.index++)),a|=(s>0?1:0)*u,u<<=1;l=o(a);break;case 1:for(a=0,p=Math.pow(2,16),u=1;u!=p;)s=m.val&m.position,m.position>>=1,0==m.position&&(m.position=n,m.val=t(m.index++)),a|=(s>0?1:0)*u,u<<=1;l=o(a);break;case 2:return""}for(f[3]=l,e=l,g.push(l);;){if(m.index>i)return"";for(a=0,p=Math.pow(2,h),u=1;u!=p;)s=m.val&m.position,m.position>>=1,0==m.position&&(m.position=n,m.val=t(m.index++)),a|=(s>0?1:0)*u,u<<=1;switch(l=a){case 0:for(a=0,p=Math.pow(2,8),u=1;u!=p;)s=m.val&m.position,m.position>>=1,0==m.position&&(m.position=n,m.val=t(m.index++)),a|=(s>0?1:0)*u,u<<=1;f[d++]=o(a),l=d-1,c--;break;case 1:for(a=0,p=Math.pow(2,16),u=1;u!=p;)s=m.val&m.position,m.position>>=1,0==m.position&&(m.position=n,m.val=t(m.index++)),a|=(s>0?1:0)*u,u<<=1;f[d++]=o(a),l=d-1,c--;break;case 2:return g.join("")}if(0==c&&(c=Math.pow(2,h),h++),f[l])v=f[l];else{if(l!==d)return null;v=e+e.charAt(0)}g.push(v),f[d++]=e+v.charAt(0),e=v,0==--c&&(c=Math.pow(2,h),h++)}}};return n}();"function"==typeof define&&define.amd?define(function(){return LZString}):"undefined"!=typeof module&&null!=module?module.exports=LZString:"undefined"!=typeof angular&&null!=angular&&angular.module("LZString",[]).factory("LZString",function(){return LZString});
///////////////////////////////////////////////

///////////////////////////////////////////////
/*!
 * PEP v0.4.3 | https://github.com/jquery/PEP
 * Copyright jQuery Foundation and other contributors | http://jquery.org/license
 */
!function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.PointerEventsPolyfill=b()}(this,function(){"use strict";function a(a,b){b=b||Object.create(null);var c=document.createEvent("Event");c.initEvent(a,b.bubbles||!1,b.cancelable||!1);
for(var d,e=2;e<m.length;e++)d=m[e],c[d]=b[d]||n[e];c.buttons=b.buttons||0;
var f=0;return f=b.pressure&&c.buttons?b.pressure:c.buttons?.5:0,c.x=c.clientX,c.y=c.clientY,c.pointerId=b.pointerId||0,c.width=b.width||0,c.height=b.height||0,c.pressure=f,c.tiltX=b.tiltX||0,c.tiltY=b.tiltY||0,c.twist=b.twist||0,c.tangentialPressure=b.tangentialPressure||0,c.pointerType=b.pointerType||"",c.hwTimestamp=b.hwTimestamp||0,c.isPrimary=b.isPrimary||!1,c}function b(){this.array=[],this.size=0}function c(a,b,c,d){this.addCallback=a.bind(d),this.removeCallback=b.bind(d),this.changedCallback=c.bind(d),A&&(this.observer=new A(this.mutationWatcher.bind(this)))}function d(a){return"body /shadow-deep/ "+e(a)}function e(a){return'[touch-action="'+a+'"]'}function f(a){return"{ -ms-touch-action: "+a+"; touch-action: "+a+"; }"}function g(){if(F){D.forEach(function(a){String(a)===a?(E+=e(a)+f(a)+"\n",G&&(E+=d(a)+f(a)+"\n")):(E+=a.selectors.map(e)+f(a.rule)+"\n",G&&(E+=a.selectors.map(d)+f(a.rule)+"\n"))});var a=document.createElement("style");a.textContent=E,document.head.appendChild(a)}}function h(){if(!window.PointerEvent){if(window.PointerEvent=a,window.navigator.msPointerEnabled){var b=window.navigator.msMaxTouchPoints;Object.defineProperty(window.navigator,"maxTouchPoints",{value:b,enumerable:!0}),u.registerSource("ms",_)}else Object.defineProperty(window.navigator,"maxTouchPoints",{value:0,enumerable:!0}),u.registerSource("mouse",N),void 0!==window.ontouchstart&&u.registerSource("touch",V);u.register(document)}}function i(a){if(!u.pointermap.has(a)){var b=new Error("InvalidPointerId");throw b.name="InvalidPointerId",b}}function j(a){for(var b=a.parentNode;b&&b!==a.ownerDocument;)b=b.parentNode;if(!b){var c=new Error("InvalidStateError");throw c.name="InvalidStateError",c}}function k(a){var b=u.pointermap.get(a);return 0!==b.buttons}function l(){window.Element&&!Element.prototype.setPointerCapture&&Object.defineProperties(Element.prototype,{setPointerCapture:{value:W},releasePointerCapture:{value:X},hasPointerCapture:{value:Y}})}
var m=["bubbles","cancelable","view","detail","screenX","screenY","clientX","clientY","ctrlKey","altKey","shiftKey","metaKey","button","relatedTarget","pageX","pageY"],n=[!1,!1,null,null,0,0,0,0,!1,!1,!1,!1,0,null,0,0],o=window.Map&&window.Map.prototype.forEach,p=o?Map:b;b.prototype={set:function(a,b){return void 0===b?this["delete"](a):(this.has(a)||this.size++,void(this.array[a]=b))},has:function(a){return void 0!==this.array[a]},"delete":function(a){this.has(a)&&(delete this.array[a],this.size--)},get:function(a){return this.array[a]},clear:function(){this.array.length=0,this.size=0},forEach:function(a,b){return this.array.forEach(function(c,d){a.call(b,c,d,this)},this)}};var q=["bubbles","cancelable","view","detail","screenX","screenY","clientX","clientY","ctrlKey","altKey","shiftKey","metaKey","button","relatedTarget","buttons","pointerId","width","height","pressure","tiltX","tiltY","pointerType","hwTimestamp","isPrimary","type","target","currentTarget","which","pageX","pageY","timeStamp"],r=[!1,!1,null,null,0,0,0,0,!1,!1,!1,!1,0,null,0,0,0,0,0,0,0,"",0,!1,"",null,null,0,0,0,0],s={pointerover:1,pointerout:1,pointerenter:1,pointerleave:1},t="undefined"!=typeof SVGElementInstance,u={pointermap:new p,eventMap:Object.create(null),captureInfo:Object.create(null),eventSources:Object.create(null),eventSourceList:[],registerSource:function(a,b){var c=b,d=c.events;d&&(d.forEach(function(a){c[a]&&(this.eventMap[a]=c[a].bind(c))},this),this.eventSources[a]=c,this.eventSourceList.push(c))},register:function(a){for(var b,c=this.eventSourceList.length,d=0;d<c&&(b=this.eventSourceList[d]);d++)
b.register.call(b,a)},unregister:function(a){for(var b,c=this.eventSourceList.length,d=0;d<c&&(b=this.eventSourceList[d]);d++)
b.unregister.call(b,a)},contains:function(a,b){try{return a.contains(b)}catch(c){return!1}},down:function(a){a.bubbles=!0,this.fireEvent("pointerdown",a)},move:function(a){a.bubbles=!0,this.fireEvent("pointermove",a)},up:function(a){a.bubbles=!0,this.fireEvent("pointerup",a)},enter:function(a){a.bubbles=!1,this.fireEvent("pointerenter",a)},leave:function(a){a.bubbles=!1,this.fireEvent("pointerleave",a)},over:function(a){a.bubbles=!0,this.fireEvent("pointerover",a)},out:function(a){a.bubbles=!0,this.fireEvent("pointerout",a)},cancel:function(a){a.bubbles=!0,this.fireEvent("pointercancel",a)},leaveOut:function(a){this.out(a),this.propagate(a,this.leave,!1)},enterOver:function(a){this.over(a),this.propagate(a,this.enter,!0)},eventHandler:function(a){if(!a._handledByPE){var b=a.type,c=this.eventMap&&this.eventMap[b];c&&c(a),a._handledByPE=!0}},listen:function(a,b){b.forEach(function(b){this.addEvent(a,b)},this)},unlisten:function(a,b){b.forEach(function(b){this.removeEvent(a,b)},this)},addEvent:function(a,b){a.addEventListener(b,this.boundHandler)},removeEvent:function(a,b){a.removeEventListener(b,this.boundHandler)},makeEvent:function(b,c){this.captureInfo[c.pointerId]&&(c.relatedTarget=null);var d=new a(b,c);return c.preventDefault&&(d.preventDefault=c.preventDefault),d._target=d._target||c.target,d},fireEvent:function(a,b){var c=this.makeEvent(a,b);return this.dispatchEvent(c)},cloneEvent:function(a){for(var b,c=Object.create(null),d=0;d<q.length;d++)b=q[d],c[b]=a[b]||r[d],!t||"target"!==b&&"relatedTarget"!==b||c[b]instanceof SVGElementInstance&&(c[b]=c[b].correspondingUseElement);return a.preventDefault&&(c.preventDefault=function(){a.preventDefault()}),c},getTarget:function(a){var b=this.captureInfo[a.pointerId];return b?a._target!==b&&a.type in s?void 0:b:a._target},propagate:function(a,b,c){for(var d=a.target,e=[];d!==document&&!d.contains(a.relatedTarget);) if(e.push(d),d=d.parentNode,!d)return;c&&e.reverse(),e.forEach(function(c){a.target=c,b.call(this,a)},this)},setCapture:function(b,c,d){this.captureInfo[b]&&this.releaseCapture(b,d),this.captureInfo[b]=c,this.implicitRelease=this.releaseCapture.bind(this,b,d),document.addEventListener("pointerup",this.implicitRelease),document.addEventListener("pointercancel",this.implicitRelease);var e=new a("gotpointercapture");e.pointerId=b,e._target=c,d||this.asyncDispatchEvent(e)},releaseCapture:function(b,c){var d=this.captureInfo[b];if(d){this.captureInfo[b]=void 0,document.removeEventListener("pointerup",this.implicitRelease),document.removeEventListener("pointercancel",this.implicitRelease);var e=new a("lostpointercapture");e.pointerId=b,e._target=d,c||this.asyncDispatchEvent(e)}},dispatchEvent:/*scope.external.dispatchEvent || */function(a){var b=this.getTarget(a);if(b)return b.dispatchEvent(a)},asyncDispatchEvent:function(a){requestAnimationFrame(this.dispatchEvent.bind(this,a))}};u.boundHandler=u.eventHandler.bind(u);var v={shadow:function(a){if(a)return a.shadowRoot||a.webkitShadowRoot},canTarget:function(a){return a&&Boolean(a.elementFromPoint)},targetingShadow:function(a){var b=this.shadow(a);if(this.canTarget(b))return b},olderShadow:function(a){var b=a.olderShadowRoot;if(!b){var c=a.querySelector("shadow");c&&(b=c.olderShadowRoot)}return b},allShadows:function(a){for(var b=[],c=this.shadow(a);c;)b.push(c),c=this.olderShadow(c);return b},searchRoot:function(a,b,c){if(a){var d,e,f=a.elementFromPoint(b,c);for(e=this.targetingShadow(f);e;){if(d=e.elementFromPoint(b,c)){var g=this.targetingShadow(d);return this.searchRoot(g,b,c)||d} e=this.olderShadow(e)} return f}},owner:function(a){
for(var b=a;b.parentNode;)b=b.parentNode;
return b.nodeType!==Node.DOCUMENT_NODE&&b.nodeType!==Node.DOCUMENT_FRAGMENT_NODE&&(b=document),b},findTarget:function(a){var b=a.clientX,c=a.clientY,d=this.owner(a.target);
return d.elementFromPoint(b,c)||(d=document),this.searchRoot(d,b,c)}},w=Array.prototype.forEach.call.bind(Array.prototype.forEach),x=Array.prototype.map.call.bind(Array.prototype.map),y=Array.prototype.slice.call.bind(Array.prototype.slice),z=Array.prototype.filter.call.bind(Array.prototype.filter),A=window.MutationObserver||window.WebKitMutationObserver,B="[touch-action]",C={subtree:!0,childList:!0,attributes:!0,attributeOldValue:!0,attributeFilter:["touch-action"]};c.prototype={watchSubtree:function(a){
//
this.observer&&v.canTarget(a)&&this.observer.observe(a,C)},enableOnSubtree:function(a){this.watchSubtree(a),a===document&&"complete"!==document.readyState?this.installOnLoad():this.installNewSubtree(a)},installNewSubtree:function(a){w(this.findElements(a),this.addElement,this)},findElements:function(a){return a.querySelectorAll?a.querySelectorAll(B):[]},removeElement:function(a){this.removeCallback(a)},addElement:function(a){this.addCallback(a)},elementChanged:function(a,b){this.changedCallback(a,b)},concatLists:function(a,b){return a.concat(y(b))},
installOnLoad:function(){document.addEventListener("readystatechange",function(){"complete"===document.readyState&&this.installNewSubtree(document)}.bind(this))},isElement:function(a){return a.nodeType===Node.ELEMENT_NODE},flattenMutationTree:function(a){
var b=x(a,this.findElements,this);
return b.push(z(a,this.isElement)),b.reduce(this.concatLists,[])},mutationWatcher:function(a){a.forEach(this.mutationHandler,this)},mutationHandler:function(a){if("childList"===a.type){var b=this.flattenMutationTree(a.addedNodes);b.forEach(this.addElement,this);var c=this.flattenMutationTree(a.removedNodes);c.forEach(this.removeElement,this)}else"attributes"===a.type&&this.elementChanged(a.target,a.oldValue)}};var D=["none","auto","pan-x","pan-y",{rule:"pan-x pan-y",selectors:["pan-x pan-y","pan-y pan-x"]}],E="",F=window.PointerEvent||window.MSPointerEvent,G=!window.ShadowDOMPolyfill&&document.head.createShadowRoot,H=u.pointermap,I=25,J=[1,4,2,8,16],K=!1;try{K=1===new MouseEvent("test",{buttons:1}).buttons}catch(L){}
var M,N={POINTER_ID:1,POINTER_TYPE:"mouse",events:["mousedown","mousemove","mouseup","mouseover","mouseout"],register:function(a){u.listen(a,this.events)},unregister:function(a){u.unlisten(a,this.events)},lastTouches:[],
isEventSimulatedFromTouch:function(a){for(var b,c=this.lastTouches,d=a.clientX,e=a.clientY,f=0,g=c.length;f<g&&(b=c[f]);f++){
var h=Math.abs(d-b.x),i=Math.abs(e-b.y);if(h<=I&&i<=I)return!0}},prepareEvent:function(a){var b=u.cloneEvent(a),c=b.preventDefault;return b.preventDefault=function(){a.preventDefault(),c()},b.pointerId=this.POINTER_ID,b.isPrimary=!0,b.pointerType=this.POINTER_TYPE,b},prepareButtonsForMove:function(a,b){var c=H.get(this.POINTER_ID);
0!==b.which&&c?a.buttons=c.buttons:a.buttons=0,b.buttons=a.buttons},mousedown:function(a){if(!this.isEventSimulatedFromTouch(a)){var b=H.get(this.POINTER_ID),c=this.prepareEvent(a);K||(c.buttons=J[c.button],b&&(c.buttons|=b.buttons),a.buttons=c.buttons),H.set(this.POINTER_ID,a),b&&0!==b.buttons?u.move(c):u.down(c)}},mousemove:function(a){if(!this.isEventSimulatedFromTouch(a)){var b=this.prepareEvent(a);K||this.prepareButtonsForMove(b,a),b.button=-1,H.set(this.POINTER_ID,a),u.move(b)}},mouseup:function(a){if(!this.isEventSimulatedFromTouch(a)){var b=H.get(this.POINTER_ID),c=this.prepareEvent(a);if(!K){var d=J[c.button];
c.buttons=b?b.buttons&~d:0,a.buttons=c.buttons}H.set(this.POINTER_ID,a),
c.buttons&=~J[c.button],0===c.buttons?u.up(c):u.move(c)}},mouseover:function(a){if(!this.isEventSimulatedFromTouch(a)){var b=this.prepareEvent(a);K||this.prepareButtonsForMove(b,a),b.button=-1,H.set(this.POINTER_ID,a),u.enterOver(b)}},mouseout:function(a){if(!this.isEventSimulatedFromTouch(a)){var b=this.prepareEvent(a);K||this.prepareButtonsForMove(b,a),b.button=-1,u.leaveOut(b)}},cancel:function(a){var b=this.prepareEvent(a);u.cancel(b),this.deactivateMouse()},deactivateMouse:function(){H["delete"](this.POINTER_ID)}},O=u.captureInfo,P=v.findTarget.bind(v),Q=v.allShadows.bind(v),R=u.pointermap,S=2500,T=200,U="touch-action",V={events:["touchstart","touchmove","touchend","touchcancel"],register:function(a){M.enableOnSubtree(a)},unregister:function(){},elementAdded:function(a){var b=a.getAttribute(U),c=this.touchActionToScrollType(b);c&&(a._scrollType=c,u.listen(a,this.events),
Q(a).forEach(function(a){a._scrollType=c,u.listen(a,this.events)},this))},elementRemoved:function(a){a._scrollType=void 0,u.unlisten(a,this.events),
Q(a).forEach(function(a){a._scrollType=void 0,u.unlisten(a,this.events)},this)},elementChanged:function(a,b){var c=a.getAttribute(U),d=this.touchActionToScrollType(c),e=this.touchActionToScrollType(b);
d&&e?(a._scrollType=d,Q(a).forEach(function(a){a._scrollType=d},this)):e?this.elementRemoved(a):d&&this.elementAdded(a)},scrollTypes:{EMITTER:"none",XSCROLLER:"pan-x",YSCROLLER:"pan-y",SCROLLER:/^(?:pan-x pan-y)|(?:pan-y pan-x)|auto$/},touchActionToScrollType:function(a){var b=a,c=this.scrollTypes;return"none"===b?"none":b===c.XSCROLLER?"X":b===c.YSCROLLER?"Y":c.SCROLLER.exec(b)?"XY":void 0},POINTER_TYPE:"touch",firstTouch:null,isPrimaryTouch:function(a){return this.firstTouch===a.identifier},setPrimaryTouch:function(a){
(0===R.size||1===R.size&&R.has(1))&&(this.firstTouch=a.identifier,this.firstXY={X:a.clientX,Y:a.clientY},this.scrolling=!1,this.cancelResetClickCount())},removePrimaryPointer:function(a){a.isPrimary&&(this.firstTouch=null,this.firstXY=null,this.resetClickCount())},clickCount:0,resetId:null,resetClickCount:function(){var a=function(){this.clickCount=0,this.resetId=null}.bind(this);this.resetId=setTimeout(a,T)},cancelResetClickCount:function(){this.resetId&&clearTimeout(this.resetId)},typeToButtons:function(a){var b=0;return"touchstart"!==a&&"touchmove"!==a||(b=1),b},touchToPointer:function(a){var b=this.currentTouchEvent,c=u.cloneEvent(a),d=c.pointerId=a.identifier+2;c.target=O[d]||P(c),c.bubbles=!0,c.cancelable=!0,c.detail=this.clickCount,c.button=0,c.buttons=this.typeToButtons(b.type),c.width=2*(a.radiusX||a.webkitRadiusX||0),c.height=2*(a.radiusY||a.webkitRadiusY||0),c.pressure=a.force||a.webkitForce||.5,c.isPrimary=this.isPrimaryTouch(a),c.pointerType=this.POINTER_TYPE,
c.altKey=b.altKey,c.ctrlKey=b.ctrlKey,c.metaKey=b.metaKey,c.shiftKey=b.shiftKey;
var e=this;return c.preventDefault=function(){e.scrolling=!1,e.firstXY=null,b.preventDefault()},c},processTouches:function(a,b){var c=a.changedTouches;this.currentTouchEvent=a;for(var d,e=0;e<c.length;e++)d=c[e],b.call(this,this.touchToPointer(d))},
shouldScroll:function(a){if(this.firstXY){var b,c=a.currentTarget._scrollType;if("none"===c)
b=!1;else if("XY"===c)
b=!0;else{var d=a.changedTouches[0],e=c,f="Y"===c?"X":"Y",g=Math.abs(d["client"+e]-this.firstXY[e]),h=Math.abs(d["client"+f]-this.firstXY[f]);
b=g>=h}return this.firstXY=null,b}},findTouch:function(a,b){for(var c,d=0,e=a.length;d<e&&(c=a[d]);d++)if(c.identifier===b)return!0},
vacuumTouches:function(a){var b=a.touches;
if(R.size>=b.length){var c=[];R.forEach(function(a,d){
if(1!==d&&!this.findTouch(b,d-2)){var e=a.out;c.push(e)}},this),c.forEach(this.cancelOut,this)}},touchstart:function(a){this.vacuumTouches(a),this.setPrimaryTouch(a.changedTouches[0]),this.dedupSynthMouse(a),this.scrolling||(this.clickCount++,this.processTouches(a,this.overDown))},overDown:function(a){R.set(a.pointerId,{target:a.target,out:a,outTarget:a.target}),u.enterOver(a),u.down(a)},touchmove:function(a){this.scrolling||(this.shouldScroll(a)?(this.scrolling=!0,this.touchcancel(a)):(a.preventDefault(),this.processTouches(a,this.moveOverOut)))},moveOverOut:function(a){var b=a,c=R.get(b.pointerId);
if(c){var d=c.out,e=c.outTarget;u.move(b),d&&e!==b.target&&(d.relatedTarget=b.target,b.relatedTarget=e,
d.target=e,b.target?(u.leaveOut(d),u.enterOver(b)):(
b.target=e,b.relatedTarget=null,this.cancelOut(b))),c.out=b,c.outTarget=b.target}},touchend:function(a){this.dedupSynthMouse(a),this.processTouches(a,this.upOut)},upOut:function(a){this.scrolling||(u.up(a),u.leaveOut(a)),this.cleanUpPointer(a)},touchcancel:function(a){this.processTouches(a,this.cancelOut)},cancelOut:function(a){u.cancel(a),u.leaveOut(a),this.cleanUpPointer(a)},cleanUpPointer:function(a){R["delete"](a.pointerId),this.removePrimaryPointer(a)},
dedupSynthMouse:function(a){var b=N.lastTouches,c=a.changedTouches[0];
if(this.isPrimaryTouch(c)){
var d={x:c.clientX,y:c.clientY};b.push(d);var e=function(a,b){var c=a.indexOf(b);c>-1&&a.splice(c,1)}.bind(null,b,d);setTimeout(e,S)}}};M=new c(V.elementAdded,V.elementRemoved,V.elementChanged,V);var W,X,Y,Z=u.pointermap,$=window.MSPointerEvent&&"number"==typeof window.MSPointerEvent.MSPOINTER_TYPE_MOUSE,_={events:["MSPointerDown","MSPointerMove","MSPointerUp","MSPointerOut","MSPointerOver","MSPointerCancel","MSGotPointerCapture","MSLostPointerCapture"],register:function(a){u.listen(a,this.events)},unregister:function(a){u.unlisten(a,this.events)},POINTER_TYPES:["","unavailable","touch","pen","mouse"],prepareEvent:function(a){var b=a;return $&&(b=u.cloneEvent(a),b.pointerType=this.POINTER_TYPES[a.pointerType]),b},cleanup:function(a){Z["delete"](a)},MSPointerDown:function(a){Z.set(a.pointerId,a);var b=this.prepareEvent(a);u.down(b)},MSPointerMove:function(a){var b=this.prepareEvent(a);u.move(b)},MSPointerUp:function(a){var b=this.prepareEvent(a);u.up(b),this.cleanup(a.pointerId)},MSPointerOut:function(a){var b=this.prepareEvent(a);u.leaveOut(b)},MSPointerOver:function(a){var b=this.prepareEvent(a);u.enterOver(b)},MSPointerCancel:function(a){var b=this.prepareEvent(a);u.cancel(b),this.cleanup(a.pointerId)},MSLostPointerCapture:function(a){var b=u.makeEvent("lostpointercapture",a);u.dispatchEvent(b)},MSGotPointerCapture:function(a){var b=u.makeEvent("gotpointercapture",a);u.dispatchEvent(b)}},aa=window.navigator;aa.msPointerEnabled?(W=function(a){i(a),j(this),k(a)&&(u.setCapture(a,this,!0),this.msSetPointerCapture(a))},X=function(a){i(a),u.releaseCapture(a,!0),this.msReleasePointerCapture(a)}):(W=function(a){i(a),j(this),k(a)&&u.setCapture(a,this)},X=function(a){i(a),u.releaseCapture(a)}),Y=function(a){return!!u.captureInfo[a]},g(),h(),l();var ba={dispatcher:u,Installer:c,PointerEvent:a,PointerMap:p,targetFinding:v};return ba});

///////////////////////////////////////////////

///////////////////////////////////////////////
var config = {"show_fabrication": false, "redraw_on_drag": true, "highlight_pin1": false, "extra_fields": [], "dark_mode": false, "bom_view": "left-right", "board_rotation": 0, "checkboxes": "Sourced,Placed", "show_silkscreen": true, "show_pads": true, "layer_view": "FB"}
///////////////////////////////////////////////

///////////////////////////////////////////////
var pcbdata = JSON.parse(LZString.decompressFromBase64("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z19WXD3Jupd00uL13terV3/2hz2Le6B2BeoT0xe+T2cuMJ2jA3t22ep+2buix1sewh1oelF3HehO3GeuO3AeoL3yy1j3bert1YC+V11uoL0Pu6YZT2lb1VOvZ3zeld2fep93TeuZ0CexV0iOuT3YOgj1mqXpBjex5Jie5amFezTknuodxgetL3LeU73Muivl8uz6xme5GIveogGpe/70guhL0BOmT2j2zb2g+770DOiL17u/b01dKN39urj31u4T1HOgyzFe7r2U2yT0GOmR1E+sB0g+hF14+g91QHa91I+z1V9ezn0724L5Nuxp16OlEKUeor3hegr3nOun1Be1hzFesH1LGtQDuwSH2bOgN0w++X1he1p3Weq+0sur51aein3oehX05u1b0gO4p0geln1yOuL0bu372mulX2gpW93iEfVhju5100+0L1vu+n02+0m1muxx2++gR3Lu8n38lEX1mOwYK3uwX3rgl72r7bH2Xexe1Y+9H0o+hN1R+w71uOsP3uO7PyR+sn0Au3F2fuj7YLOi30xu5W2K+ov2LO34CEeqdniEDNhjuvr2A+xl0O+y13PRbD2B+9xzPejb3Se+70TuiP1Pes30eelj0rO871EOvD1tuof35OiEy0+q303etP2qO3z3628Py9+vPVmekn08+iyxgesv3Rua50b+1P15+lN1o+pV0E+kN2J+g/0T+r30axBb22Ogb0V+8H2MAXJQ/WpW3Q+uX02evv20O/X30Ow30l+830m+s70v+g52t+hV3Fe7p4iep32IOa93iENWAa+qG1eejF1n+z/39+xv0SekAO7kIF3iEVWDu+jt2e+yL2/+s20M+vZ1QQb32l+7X3P+2OVx+ogMG+/AMCujp0yY6N0FQygN4O3kLABsl2Pu013iEQGDoBn33f+1H1T+vF24Bp90UBoH3T26gOT+0Wowe+P0k2tTBjWUgP8lYAPYB121RI/t1MBsgDiEa+CQBgyzr+hAM9e5v0feyErNe0NwzuvhrZ+pf0vejV1huqn2lOzgMp++1yyu7f2Devr3iEeGDsB6f0WBqd1mBnF3SBxn2xuvX1Neur1mNNz0aB1n2+Bj13OByJ2KBot0iAcQgsoWv3Ze4INLe7gPwBmANYBuIOv+/wNyOwb0Te8QiCoMd3WBlIN++4P25+9wNfeuH3G+0P37++gOPeie3IxB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"))
///////////////////////////////////////////////

///////////////////////////////////////////////
/* Utility functions */

var storagePrefix = 'KiCad_HTML_BOM__' + pcbdata.metadata.title + '__' +
  pcbdata.metadata.revision + '__#';
var storage;

function initStorage(key) {
  try {
    window.localStorage.getItem("blank");
    storage = window.localStorage;
  } catch (e) {
    // localStorage not available
  }
  if (!storage) {
    try {
      window.sessionStorage.getItem("blank");
      storage = window.sessionStorage;
    } catch (e) {
      // sessionStorage also not available
    }
  }
}

function readStorage(key) {
  if (storage) {
    return storage.getItem(storagePrefix + key);
  } else {
    return null;
  }
}

function writeStorage(key, value) {
  if (storage) {
    storage.setItem(storagePrefix + key, value);
  }
}

function fancyDblClickHandler(el, onsingle, ondouble) {
  return function() {
    if (el.getAttribute("data-dblclick") == null) {
      el.setAttribute("data-dblclick", 1);
      setTimeout(function() {
        if (el.getAttribute("data-dblclick") == 1) {
          onsingle();
        }
        el.removeAttribute("data-dblclick");
      }, 200);
    } else {
      el.removeAttribute("data-dblclick");
      ondouble();
    }
  }
}

function smoothScrollToRow(rowid) {
  document.getElementById(rowid).scrollIntoView({
    behavior: "smooth",
    block: "center",
    inline: "nearest"
  });
}

function focusInputField(input) {
  input.scrollIntoView(false);
  input.focus();
  input.select();
}

function copyToClipboard() {
  var text = '';
  for (var node of bomhead.childNodes[0].childNodes) {
    if (node.firstChild) {
      text = text + node.firstChild.nodeValue;
    }
    if (node != bomhead.childNodes[0].lastChild) {
      text += '\t';
    }
  }
  text += '\n';
  for (var row of bombody.childNodes) {
    for (var cell of row.childNodes) {
      for (var node of cell.childNodes) {
        if (node.nodeName == "INPUT") {
          if (node.checked) {
            text = text + '✓';
          }
        } else if (node.nodeName == "MARK") {
          text = text + node.firstChild.nodeValue;
        } else {
          text = text + node.nodeValue;
        }
      }
      if (cell != row.lastChild) {
        text += '\t';
      }
    }
    text += '\n';
  }
  var textArea = document.createElement("textarea");
  textArea.classList.add('clipboard-temp');
  textArea.value = text;

  document.body.appendChild(textArea);
  textArea.focus();
  textArea.select();

  try {
    if (document.execCommand('copy')) {
      console.log('Bom copied to clipboard.');
    }
  } catch (err) {
    console.log('Can not copy to clipboard.');
  }

  document.body.removeChild(textArea);
}

function removeGutterNode(node) {
  for (var i = 0; i < node.childNodes.length; i++) {
    if (node.childNodes[i].classList &&
      node.childNodes[i].classList.contains("gutter")) {
      node.removeChild(node.childNodes[i]);
      break;
    }
  }
}

function cleanGutters() {
  removeGutterNode(document.getElementById("bot"));
  removeGutterNode(document.getElementById("canvasdiv"));
}

var units = {
  prefixes: {
    giga: ["G", "g", "giga", "Giga", "GIGA"],
    mega: ["M", "mega", "Mega", "MEGA"],
    kilo: ["K", "k", "kilo", "Kilo", "KILO"],
    milli: ["m", "milli", "Milli", "MILLI"],
    micro: ["U", "u", "micro", "Micro", "MICRO", "μ", "µ"], // different utf8 μ
    nano: ["N", "n", "nano", "Nano", "NANO"],
    pico: ["P", "p", "pico", "Pico", "PICO"],
  },
  unitsShort: ["R", "r", "Ω", "F", "f", "H", "h"],
  unitsLong: [
    "OHM", "Ohm", "ohm", "ohms",
    "FARAD", "Farad", "farad",
    "HENRY", "Henry", "henry"
  ],
  getMultiplier: function(s) {
    if (this.prefixes.giga.includes(s)) return 1e9;
    if (this.prefixes.mega.includes(s)) return 1e6;
    if (this.prefixes.kilo.includes(s)) return 1e3;
    if (this.prefixes.milli.includes(s)) return 1e-3;
    if (this.prefixes.micro.includes(s)) return 1e-6;
    if (this.prefixes.nano.includes(s)) return 1e-9;
    if (this.prefixes.pico.includes(s)) return 1e-12;
    return 1;
  },
  valueRegex: null,
}

function initUtils() {
  var allPrefixes = units.prefixes.giga
                    .concat(units.prefixes.mega)
                    .concat(units.prefixes.kilo)
                    .concat(units.prefixes.milli)
                    .concat(units.prefixes.micro)
                    .concat(units.prefixes.nano)
                    .concat(units.prefixes.pico);
  var allUnits = units.unitsShort.concat(units.unitsLong);
  units.valueRegex = new RegExp("^([0-9\.]+)" +
                         "\\s*(" + allPrefixes.join("|") + ")?" +
                         "(" + allUnits.join("|") + ")?" +
                         "(\\b.*)?$", "");
  units.valueAltRegex = new RegExp("^([0-9]*)" +
                         "(" + units.unitsShort.join("|") + ")?" +
                         "([GgMmKkUuNnPp])?" +
                         "([0-9]*)" +
                         "(\\b.*)?$", "");
  for (var bom_type of ["both", "F", "B"]) {
    for (var row of pcbdata.bom[bom_type]) {
      row.push(parseValue(row[1], row[3][0][0]));
    }
  }
}

function parseValue(val, ref) {
  var inferUnit = (unit, ref) => {
    if (unit) {
      unit = unit.toLowerCase();
      if (unit == 'Ω' || unit == "ohm" || unit == "ohms") {
        unit = 'r';
      }
      unit = unit[0];
    } else {
      ref = /^([a-z]+)\d+$/i.exec(ref);
      if (ref) {
        ref = ref[1].toLowerCase();
        if (ref == "c") unit = 'f';
        else if (ref == "l") unit = 'h';
        else if (ref == "r" || ref == "rv") unit = 'r';
        else unit = null;
      }
    }
    return unit;
  };
  val = val.replace(/,/g, "");
  var match = units.valueRegex.exec(val);
  var unit;
  if (match) {
    val = parseFloat(match[1]);
    if (match[2]) {
      val = val * units.getMultiplier(match[2]);
    }
    unit = inferUnit(match[3], ref);
    if (!unit) return null;
    else return {
      val: val,
      unit: unit,
      extra: match[4],
    }
  }
  match = units.valueAltRegex.exec(val);
  if (match && (match[1] || match[4])) {
    val = parseFloat(match[1] + "." + match[4]);
    if (match[3]) {
      val = val * units.getMultiplier(match[3]);
    }
    unit = inferUnit(match[2], ref);
    if (!unit) return null;
    else return {
      val: val,
      unit: unit,
      extra: match[5],
    }
  }
  return null;
}

function valueCompare(a, b, stra, strb) {
  if (a === null && b === null) {
    // Failed to parse both values, compare them as strings.
    if (stra != strb) return stra > strb ? 1 : -1;
    else return 0;
  } else if (a === null) {
    return 1;
  } else if (b === null) {
    return -1;
  } else {
    if (a.unit != b.unit) return a.unit > b.unit ? 1 : -1;
    else if (a.val != b.val) return a.val > b.val ? 1 : -1;
    else if (a.extra != b.extra) return a.extra > b.extra ? 1 : -1;
    else return 0;
  }
}

function validateSaveImgDimension(element) {
  var valid = false;
  var intValue = 0;
  if (/^[1-9]\d*$/.test(element.value)) {
    intValue = parseInt(element.value);
    if (intValue <= 16000) {
      valid = true;
    }
  }
  if (valid) {
    element.classList.remove("invalid");
  } else {
    element.classList.add("invalid");
  }
  return intValue;
}

function saveImage(layer) {
  var width = validateSaveImgDimension(document.getElementById("render-save-width"));
  var height = validateSaveImgDimension(document.getElementById("render-save-height"));
  var bgcolor = null;
  if (!document.getElementById("render-save-transparent").checked) {
    var style = getComputedStyle(topmostdiv);
    bgcolor = style.getPropertyValue("background-color");
  }
  if (!width || !height) return;

  // Prepare image
  var canvas = document.createElement("canvas");
  var layerdict = {
    transform: {
      x: 0,
      y: 0,
      s: 1,
      panx: 0,
      pany: 0,
      zoom: 1,
    },
    bg: canvas,
    fab: canvas,
    silk: canvas,
    highlight: canvas,
    layer: layer,
  }
  // Do the rendering
  recalcLayerScale(layerdict, width, height);
  prepareLayer(layerdict);
  clearCanvas(canvas, bgcolor);
  drawBackground(layerdict, false);
  drawHighlightsOnLayer(layerdict, false);

  // Save image
  var imgdata = canvas.toDataURL("image/png");

  var filename = pcbdata.metadata.title;
  if (pcbdata.metadata.revision) {
    filename += `.${pcbdata.metadata.revision}`;
  }
  filename += `.${layer}.png`;
  saveFile(filename, dataURLtoBlob(imgdata));
}

function saveSettings() {
  var data = {
    type: "InteractiveHtmlBom settings",
    version: 1,
    pcbmetadata: pcbdata.metadata,
    settings: settings,
  }
  var blob = new Blob([JSON.stringify(data, null, 4)], {type: "application/json"});
  saveFile(`${pcbdata.metadata.title}.settings.json`, blob);
}

function loadSettings() {
  var input = document.createElement("input");
  input.type = "file";
  input.accept = ".settings.json";
  input.onchange = function(e) {
    var file = e.target.files[0];
    var reader = new FileReader();
    reader.onload = readerEvent => {
      var content = readerEvent.target.result;
      var newSettings;
      try {
        newSettings = JSON.parse(content);
      } catch(e) {
        alert("Selected file is not InteractiveHtmlBom settings file.");
        return;
      }
      if (newSettings.type != "InteractiveHtmlBom settings") {
        alert("Selected file is not InteractiveHtmlBom settings file.");
        return;
      }
      var metadataMatches = newSettings.hasOwnProperty("pcbmetadata");
      if (metadataMatches) {
        for (var k in pcbdata.metadata) {
          if (!newSettings.pcbmetadata.hasOwnProperty(k) || newSettings.pcbmetadata[k] != pcbdata.metadata[k]) {
            metadataMatches = false;
          }
        }
      }
      if (!metadataMatches) {
        var currentMetadata = JSON.stringify(pcbdata.metadata, null, 4);
        var fileMetadata = JSON.stringify(newSettings.pcbmetadata, null, 4);
        if (!confirm(
          `Settins file metadata does not match current metadata.\n\n` +
          `Page metadata:\n${currentMetadata}\n\n` +
          `Settings file metadata:\n${fileMetadata}\n\n` +
          `Press OK if you would like to import settings anyway.`)) {
          return;
        }
      }
      overwriteSettings(newSettings.settings);
    }
    reader.readAsText(file, 'UTF-8');
  }
  input.click();
}

function overwriteSettings(newSettings) {
  initDone = false;
  Object.assign(settings, newSettings);
  writeStorage("bomlayout", settings.bomlayout);
  writeStorage("bommode", settings.bommode);
  writeStorage("canvaslayout", settings.canvaslayout);
  writeStorage("bomCheckboxes", settings.checkboxes.join(","));
  document.getElementById("bomCheckboxes").value = settings.checkboxes.join(",");
  for (var checkbox of settings.checkboxes) {
    writeStorage("checkbox_" + checkbox, settings.checkboxStoredRefs[checkbox]);
  }
  writeStorage("darkenWhenChecked", settings.darkenWhenChecked);
  padsVisible(settings.renderPads);
  document.getElementById("padsCheckbox").checked = settings.renderPads;
  fabricationVisible(settings.renderFabrication);
  document.getElementById("fabricationCheckbox").checked = settings.renderFabrication;
  silkscreenVisible(settings.renderSilkscreen);
  document.getElementById("silkscreenCheckbox").checked = settings.renderSilkscreen;
  referencesVisible(settings.renderReferences);
  document.getElementById("referencesCheckbox").checked = settings.renderReferences;
  valuesVisible(settings.renderValues);
  document.getElementById("valuesCheckbox").checked = settings.renderValues;
  tracksVisible(settings.renderTracks);
  document.getElementById("tracksCheckbox").checked = settings.renderTracks;
  zonesVisible(settings.renderZones);
  document.getElementById("zonesCheckbox").checked = settings.renderZones;
  dnpOutline(settings.renderDnpOutline);
  document.getElementById("dnpOutlineCheckbox").checked = settings.renderDnpOutline;
  setRedrawOnDrag(settings.redrawOnDrag);
  document.getElementById("dragCheckbox").checked = settings.redrawOnDrag;
  setDarkMode(settings.darkMode);
  document.getElementById("darkmodeCheckbox").checked = settings.darkMode;
  setHighlightPin1(settings.highlightpin1);
  document.getElementById("highlightpin1Checkbox").checked = settings.highlightpin1;
  writeStorage("boardRotation", settings.boardRotation);
  document.getElementById("boardRotation").value = settings.boardRotation / 5;
  document.getElementById("rotationDegree").textContent = settings.boardRotation;
  initDone = true;
  prepCheckboxes();
  changeBomLayout(settings.bomlayout);
}

function saveFile(filename, blob) {
  var link = document.createElement("a");
  var objurl = URL.createObjectURL(blob);
  link.download = filename;
  link.href = objurl;
  link.click();
}

function dataURLtoBlob(dataurl) {
  var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
      bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
  while(n--){
      u8arr[n] = bstr.charCodeAt(n);
  }
  return new Blob([u8arr], {type:mime});
}

var settings = {
  canvaslayout: "default",
  bomlayout: "default",
  bommode: "grouped",
  checkboxes: [],
  checkboxStoredRefs: {},
  darkMode: false,
  highlightpin1: false,
  redrawOnDrag: true,
  boardRotation: 0,
  renderPads: true,
  renderReferences: true,
  renderValues: true,
  renderSilkscreen: true,
  renderFabrication: true,
  renderDnpOutline: false,
  renderTracks: true,
  renderZones: true,
}

function initDefaults() {
  settings.bomlayout = readStorage("bomlayout");
  if (settings.bomlayout === null) {
    settings.bomlayout = config.bom_view;
  }
  if (!['bom-only', 'left-right', 'top-bottom'].includes(settings.bomlayout)) {
    settings.bomlayout = config.bom_view;
  }
  settings.bommode = readStorage("bommode");
  if (settings.bommode === null) {
    settings.bommode = "grouped";
  }
  if (!["grouped", "ungrouped", "netlist"].includes(settings.bommode)) {
    settings.bommode = "grouped";
  }
  settings.canvaslayout = readStorage("canvaslayout");
  if (settings.canvaslayout === null) {
    settings.canvaslayout = config.layer_view;
  }
  var bomCheckboxes = readStorage("bomCheckboxes");
  if (bomCheckboxes === null) {
    bomCheckboxes = config.checkboxes;
  }
  settings.checkboxes = bomCheckboxes.split(",").filter((e) => e);
  document.getElementById("bomCheckboxes").value = bomCheckboxes;

  settings.darkenWhenChecked = readStorage("darkenWhenChecked") || "";
  populateDarkenWhenCheckedOptions();

  function initBooleanSetting(storageString, def, elementId, func) {
    var b = readStorage(storageString);
    if (b === null) {
      b = def;
    } else {
      b = (b == "true");
    }
    document.getElementById(elementId).checked = b;
    func(b);
  }

  initBooleanSetting("padsVisible", config.show_pads, "padsCheckbox", padsVisible);
  initBooleanSetting("fabricationVisible", config.show_fabrication, "fabricationCheckbox", fabricationVisible);
  initBooleanSetting("silkscreenVisible", config.show_silkscreen, "silkscreenCheckbox", silkscreenVisible);
  initBooleanSetting("referencesVisible", true, "referencesCheckbox", referencesVisible);
  initBooleanSetting("valuesVisible", true, "valuesCheckbox", valuesVisible);
  if ("tracks" in pcbdata) {
    initBooleanSetting("tracksVisible", true, "tracksCheckbox", tracksVisible);
    initBooleanSetting("zonesVisible", true, "zonesCheckbox", zonesVisible);
  } else {
    document.getElementById("tracksAndZonesCheckboxes").style.display = "none";
    tracksVisible(false);
    zonesVisible(false);
  }
  initBooleanSetting("dnpOutline", false, "dnpOutlineCheckbox", dnpOutline);
  initBooleanSetting("redrawOnDrag", config.redraw_on_drag, "dragCheckbox", setRedrawOnDrag);
  initBooleanSetting("darkmode", config.dark_mode, "darkmodeCheckbox", setDarkMode);
  initBooleanSetting("highlightpin1", config.highlight_pin1, "highlightpin1Checkbox", setHighlightPin1);
  settings.boardRotation = readStorage("boardRotation");
  if (settings.boardRotation === null) {
    settings.boardRotation = config.board_rotation * 5;
  } else {
    settings.boardRotation = parseInt(settings.boardRotation);
  }
  document.getElementById("boardRotation").value = settings.boardRotation / 5;
  document.getElementById("rotationDegree").textContent = settings.boardRotation;
}

// Helper classes for user js callbacks.

const IBOM_EVENT_TYPES = {
  ALL: "all",
  HIGHLIGHT_EVENT: "highlightEvent",
  CHECKBOX_CHANGE_EVENT: "checkboxChangeEvent",
  BOM_BODY_CHANGE_EVENT: "bomBodyChangeEvent",
}

const EventHandler = {
  callbacks: {},
  init: function() {
    for (eventType of Object.values(IBOM_EVENT_TYPES))
      this.callbacks[eventType] = [];
  },
  registerCallback: function(eventType, callback) {
    this.callbacks[eventType].push(callback);
  },
  emitEvent: function(eventType, eventArgs) {
    event = {
      eventType: eventType,
      args: eventArgs,
    }
    var callback;
    for(callback of this.callbacks[eventType])
      callback(event);
    for(callback of this.callbacks[IBOM_EVENT_TYPES.ALL])
      callback(event);
  }
}
EventHandler.init();

///////////////////////////////////////////////

///////////////////////////////////////////////
/* PCB rendering code */

var emptyContext2d = document.createElement("canvas").getContext("2d");

function deg2rad(deg) {
  return deg * Math.PI / 180;
}

function calcFontPoint(linepoint, text, offsetx, offsety, tilt) {
  var point = [
    linepoint[0] * text.width + offsetx,
    linepoint[1] * text.height + offsety
  ];
  // This approximates pcbnew behavior with how text tilts depending on horizontal justification
  point[0] -= (linepoint[1] + 0.5 * (1 + text.justify[0])) * text.height * tilt;
  return point;
}

function drawtext(ctx, text, color, flip) {
  if ("ref" in text && !settings.renderReferences) return;
  if ("val" in text && !settings.renderValues) return;
  ctx.save();
  ctx.fillStyle = color;
  ctx.strokeStyle = color;
  ctx.lineCap = "round";
  ctx.lineJoin = "round";
  ctx.lineWidth = text.thickness;
  if (text.svgpath) {
    ctx.stroke(new Path2D(text.svgpath));
    ctx.restore();
    return;
  }
  ctx.translate(...text.pos);
  ctx.translate(text.thickness * 0.5, 0);
  var angle = -text.angle;
  if (text.attr.includes("mirrored")) {
    ctx.scale(-1, 1);
    angle = -angle;
  }
  var tilt = 0;
  if (text.attr.includes("italic")) {
    tilt = 0.125;
  }
  var interline = text.height * 1.5 + text.thickness;
  var txt = text.text.split("\n");
  // KiCad ignores last empty line.
  if (txt[txt.length - 1] == '') txt.pop();
  ctx.rotate(deg2rad(angle));
  var offsety = (1 - text.justify[1]) / 2 * text.height; // One line offset
  offsety -= (txt.length - 1) * (text.justify[1] + 1) / 2 * interline; // Multiline offset
  for (var i in txt) {
    var lineWidth = text.thickness + interline / 2 * tilt;
    for (var j = 0; j < txt[i].length; j++) {
      if (txt[i][j] == '\t') {
        var fourSpaces = 4 * pcbdata.font_data[' '].w * text.width;
        lineWidth += fourSpaces - lineWidth % fourSpaces;
      } else {
        if (txt[i][j] == '~') {
          j++;
          if (j == txt[i].length)
            break;
        }
        lineWidth += pcbdata.font_data[txt[i][j]].w * text.width;
      }
    }
    var offsetx = -lineWidth * (text.justify[0] + 1) / 2;
    var inOverbar = false;
    for (var j = 0; j < txt[i].length; j++) {
      if (txt[i][j] == '\t') {
        var fourSpaces = 4 * pcbdata.font_data[' '].w * text.width;
        offsetx += fourSpaces - offsetx % fourSpaces;
        continue;
      } else if (txt[i][j] == '~') {
        j++;
        if (j == txt[i].length)
          break;
        if (txt[i][j] != '~') {
          inOverbar = !inOverbar;
        }
      }
      var glyph = pcbdata.font_data[txt[i][j]];
      if (inOverbar) {
        var overbarStart = [offsetx, -text.height * 1.4 + offsety];
        var overbarEnd = [offsetx + text.width * glyph.w, overbarStart[1]];

        if (!lastHadOverbar) {
          overbarStart[0] += text.height * 1.4 * tilt;
          lastHadOverbar = true;
        }
        ctx.beginPath();
        ctx.moveTo(...overbarStart);
        ctx.lineTo(...overbarEnd);
        ctx.stroke();
      } else {
        lastHadOverbar = false;
      }
      for (var line of glyph.l) {
        ctx.beginPath();
        ctx.moveTo(...calcFontPoint(line[0], text, offsetx, offsety, tilt));
        for (var k = 1; k < line.length; k++) {
          ctx.lineTo(...calcFontPoint(line[k], text, offsetx, offsety, tilt));
        }
        ctx.stroke();
      }
      offsetx += glyph.w * text.width;
    }
    offsety += interline;
  }
  ctx.restore();
}

function drawedge(ctx, scalefactor, edge, color) {
  ctx.strokeStyle = color;
  ctx.lineWidth = Math.max(1 / scalefactor, edge.width);
  ctx.lineCap = "round";
  if (edge.svgpath) {
    ctx.stroke(new Path2D(edge.svgpath));
  } else {
    ctx.beginPath();
    if (edge.type == "segment") {
      ctx.moveTo(...edge.start);
      ctx.lineTo(...edge.end);
    }
    if (edge.type == "rect") {
      ctx.moveTo(...edge.start);
      ctx.lineTo(edge.start[0], edge.end[1]);
      ctx.lineTo(...edge.end);
      ctx.lineTo(edge.end[0], edge.start[1]);
      ctx.lineTo(...edge.start);
    }
    if (edge.type == "arc") {
      ctx.arc(
        ...edge.start,
        edge.radius,
        deg2rad(edge.startangle),
        deg2rad(edge.endangle));
    }
    if (edge.type == "circle") {
      ctx.arc(
        ...edge.start,
        edge.radius,
        0, 2 * Math.PI);
      ctx.closePath();
    }
    if (edge.type == "curve") {
      ctx.moveTo(...edge.start);
      ctx.bezierCurveTo(...edge.cpa, ...edge.cpb, ...edge.end);
    }
    ctx.stroke();
  }
}

function getChamferedRectPath(size, radius, chamfpos, chamfratio) {
  // chamfpos is a bitmask, left = 1, right = 2, bottom left = 4, bottom right = 8
  var path = new Path2D();
  var width = size[0];
  var height = size[1];
  var x = width * -0.5;
  var y = height * -0.5;
  var chamfOffset = Math.min(width, height) * chamfratio;
  path.moveTo(x, 0);
  if (chamfpos & 4) {
    path.lineTo(x, y + height - chamfOffset);
    path.lineTo(x + chamfOffset, y + height);
    path.lineTo(0, y + height);
  } else {
    path.arcTo(x, y + height, x + width, y + height, radius);
  }
  if (chamfpos & 8) {
    path.lineTo(x + width - chamfOffset, y + height);
    path.lineTo(x + width, y + height - chamfOffset);
    path.lineTo(x + width, 0);
  } else {
    path.arcTo(x + width, y + height, x + width, y, radius);
  }
  if (chamfpos & 2) {
    path.lineTo(x + width, y + chamfOffset);
    path.lineTo(x + width - chamfOffset, y);
    path.lineTo(0, y);
  } else {
    path.arcTo(x + width, y, x, y, radius);
  }
  if (chamfpos & 1) {
    path.lineTo(x + chamfOffset, y);
    path.lineTo(x, y + chamfOffset);
    path.lineTo(x, 0);
  } else {
    path.arcTo(x, y, x, y + height, radius);
  }
  path.closePath();
  return path;
}

function getOblongPath(size) {
  return getChamferedRectPath(size, Math.min(size[0], size[1]) / 2, 0, 0);
}

function getPolygonsPath(shape) {
  if (shape.path2d) {
    return shape.path2d;
  }
  if (shape.svgpath) {
    shape.path2d = new Path2D(shape.svgpath);
  } else {
    var path = new Path2D();
    for (var polygon of shape.polygons) {
      path.moveTo(...polygon[0]);
      for (var i = 1; i < polygon.length; i++) {
        path.lineTo(...polygon[i]);
      }
      path.closePath();
    }
    shape.path2d = path;
  }
  return shape.path2d;
}

function drawPolygonShape(ctx, shape, color) {
  ctx.save();
  ctx.fillStyle = color;
  if (!shape.svgpath) {
    ctx.translate(...shape.pos);
    ctx.rotate(deg2rad(-shape.angle));
  }
  ctx.fill(getPolygonsPath(shape));
  ctx.restore();
}

function drawDrawing(ctx, layer, scalefactor, drawing, color) {
  if (["segment", "arc", "circle", "curve"].includes(drawing.type)) {
    drawedge(ctx, scalefactor, drawing, color);
  } else if (drawing.type == "polygon") {
    drawPolygonShape(ctx, drawing, color);
  } else {
    drawtext(ctx, drawing, color, layer == "B");
  }
}

function getCirclePath(radius) {
  var path = new Path2D();
  path.arc(0, 0, radius, 0, 2 * Math.PI);
  path.closePath();
  return path;
}

function getCachedPadPath(pad) {
  if (!pad.path2d) {
    // if path2d is not set, build one and cache it on pad object
    if (pad.shape == "rect") {
      pad.path2d = new Path2D();
      pad.path2d.rect(...pad.size.map(c => -c * 0.5), ...pad.size);
    } else if (pad.shape == "oval") {
      pad.path2d = getOblongPath(pad.size);
    } else if (pad.shape == "circle") {
      pad.path2d = getCirclePath(pad.size[0] / 2);
    } else if (pad.shape == "roundrect") {
      pad.path2d = getChamferedRectPath(pad.size, pad.radius, 0, 0);
    } else if (pad.shape == "chamfrect") {
      pad.path2d = getChamferedRectPath(pad.size, pad.radius, pad.chamfpos, pad.chamfratio)
    } else if (pad.shape == "custom") {
      pad.path2d = getPolygonsPath(pad);
    }
  }
  return pad.path2d;
}

function drawPad(ctx, pad, color, outline, hole) {
  ctx.save();
  ctx.translate(...pad.pos);
  ctx.rotate(deg2rad(pad.angle));
  if (pad.offset) {
    ctx.translate(...pad.offset);
  }
  ctx.fillStyle = color;
  ctx.strokeStyle = color;
  var path = getCachedPadPath(pad);
  if (outline) {
    ctx.stroke(path);
  } else {
    ctx.fill(path);
  }
  if (pad.type == "th" && hole) {
    if (pad.offset) {
      ctx.translate(-pad.offset[0], -pad.offset[1]);
    }
    ctx.fillStyle = "#CCCCCC";
    if (pad.drillshape == "oblong") {
      ctx.fill(getOblongPath(pad.drillsize));
    } else {
      ctx.fill(getCirclePath(pad.drillsize[0] / 2));
    }
  }
  ctx.restore();
}

function drawModule(ctx, layer, scalefactor, module, padcolor, outlinecolor, highlight, outline) {
  if (highlight) {
    // draw bounding box
    if (module.layer == layer) {
      ctx.save();
      ctx.globalAlpha = 0.2;
      ctx.translate(...module.bbox.pos);
      ctx.rotate(deg2rad(-module.bbox.angle));
      ctx.translate(...module.bbox.relpos);
      ctx.fillStyle = padcolor;
      ctx.fillRect(0, 0, ...module.bbox.size);
      ctx.globalAlpha = 1;
      ctx.strokeStyle = padcolor;
      ctx.strokeRect(0, 0, ...module.bbox.size);
      ctx.restore();
    }
  }
  // draw drawings
  for (var drawing of module.drawings) {
    if (drawing.layer == layer) {
      drawDrawing(ctx, layer, scalefactor, drawing.drawing, padcolor);
    }
  }
  // draw pads
  if (settings.renderPads) {
    for (var pad of module.pads) {
      if (pad.layers.includes(layer)) {
        drawPad(ctx, pad, padcolor, outline, true);
        if (pad.pin1 && settings.highlightpin1) {
          drawPad(ctx, pad, outlinecolor, true, false);
        }
      }
    }
  }
}

function drawEdgeCuts(canvas, scalefactor) {
  var ctx = canvas.getContext("2d");
  var edgecolor = getComputedStyle(topmostdiv).getPropertyValue('--pcb-edge-color');
  for (var edge of pcbdata.edges) {
    drawedge(ctx, scalefactor, edge, edgecolor);
  }
}

function drawModules(canvas, layer, scalefactor, highlight) {
  var ctx = canvas.getContext("2d");
  ctx.lineWidth = 3 / scalefactor;
  var style = getComputedStyle(topmostdiv);
  var padcolor = style.getPropertyValue('--pad-color');
  var outlinecolor = style.getPropertyValue('--pin1-outline-color');
  if (highlight) {
    padcolor = style.getPropertyValue('--pad-color-highlight');
    outlinecolor = style.getPropertyValue('--pin1-outline-color-highlight');
  }
  for (var i = 0; i < pcbdata.modules.length; i++) {
    var mod = pcbdata.modules[i];
    var outline = settings.renderDnpOutline && pcbdata.bom.skipped.includes(i);
    if (!highlight || highlightedModules.includes(i)) {
      drawModule(ctx, layer, scalefactor, mod, padcolor, outlinecolor, highlight, outline);
    }
  }
}

function drawBgLayer(layername, canvas, layer, scalefactor, edgeColor, polygonColor, textColor) {
  var ctx = canvas.getContext("2d");
  for (var d of pcbdata[layername][layer]) {
    if (["segment", "arc", "circle", "curve", "rect"].includes(d.type)) {
      drawedge(ctx, scalefactor, d, edgeColor);
    } else if (d.type == "polygon") {
      drawPolygonShape(ctx, d, polygonColor);
    } else {
      drawtext(ctx, d, textColor, layer == "B");
    }
  }
}

function drawTracks(canvas, layer, color, highlight) {
  ctx = canvas.getContext("2d");
  ctx.strokeStyle = color;
  ctx.lineCap = "round";
  for(var track of pcbdata.tracks[layer]) {
    if (highlight && highlightedNet != track.net) continue;
    ctx.lineWidth = track.width;
    ctx.beginPath();
    ctx.moveTo(...track.start);
    ctx.lineTo(...track.end);
    ctx.stroke();
  }
}

function drawZones(canvas, layer, color, highlight) {
  ctx = canvas.getContext("2d");
  ctx.strokeStyle = color;
  ctx.fillStyle = color;
  ctx.lineJoin = "round";
  for(var zone of pcbdata.zones[layer]) {
    if (!zone.path2d) {
      zone.path2d = getPolygonsPath(zone);
    }
    if (highlight && highlightedNet != zone.net) continue;
    ctx.fill(zone.path2d);
    if (zone.width > 0) {
      ctx.lineWidth = zone.width;
      ctx.stroke(zone.path2d);
    }
  }
}

function clearCanvas(canvas, color = null) {
  var ctx = canvas.getContext("2d");
  ctx.save();
  ctx.setTransform(1, 0, 0, 1, 0, 0);
  if (color) {
    ctx.fillStyle = color;
    ctx.fillRect(0, 0, canvas.width, canvas.height);
  } else {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
  }
  ctx.restore();
}

function drawNets(canvas, layer, highlight) {
  var style = getComputedStyle(topmostdiv);
  if (settings.renderTracks) {
    var trackColor = style.getPropertyValue(highlight ? '--track-color-highlight' : '--track-color');
    drawTracks(canvas, layer, trackColor, highlight);
  }
  if (settings.renderZones) {
    var zoneColor = style.getPropertyValue(highlight ? '--zone-color-highlight' : '--zone-color');
    drawZones(canvas, layer, zoneColor, highlight);
  }
  if (highlight && settings.renderPads) {
    var padColor = style.getPropertyValue('--pad-color-highlight');
    var ctx = canvas.getContext("2d");
    for (var mod of pcbdata.modules) {
      // draw pads
      for (var pad of mod.pads) {
        if (highlightedNet != pad.net) continue;
        if (pad.layers.includes(layer)) {
          drawPad(ctx, pad, padColor, false, true);
        }
      }
    }
  }
}

function drawHighlightsOnLayer(canvasdict, clear = true) {
  if (clear) {
    clearCanvas(canvasdict.highlight);
  }
  if (highlightedModules.length > 0) {
    drawModules(canvasdict.highlight, canvasdict.layer,
      canvasdict.transform.s * canvasdict.transform.zoom, true);
  }
  if (highlightedNet !== null) {
    drawNets(canvasdict.highlight, canvasdict.layer, true);
  }
}

function drawHighlights() {
  drawHighlightsOnLayer(allcanvas.front);
  drawHighlightsOnLayer(allcanvas.back);
}

function drawBackground(canvasdict, clear = true) {
  if (clear) {
    clearCanvas(canvasdict.bg);
    clearCanvas(canvasdict.fab);
    clearCanvas(canvasdict.silk);
  }

  drawNets(canvasdict.bg, canvasdict.layer, false);
  drawModules(canvasdict.bg, canvasdict.layer,
    canvasdict.transform.s * canvasdict.transform.zoom, false);

  drawEdgeCuts(canvasdict.bg, canvasdict.transform.s);

  var style = getComputedStyle(topmostdiv);
  var edgeColor = style.getPropertyValue('--silkscreen-edge-color');
  var polygonColor = style.getPropertyValue('--silkscreen-polygon-color');
  var textColor = style.getPropertyValue('--silkscreen-text-color');
  if (settings.renderSilkscreen) {
    drawBgLayer(
      "silkscreen", canvasdict.silk, canvasdict.layer,
      canvasdict.transform.s * canvasdict.transform.zoom,
      edgeColor, polygonColor, textColor);
  }
  edgeColor = style.getPropertyValue('--fabrication-edge-color');
  polygonColor = style.getPropertyValue('--fabrication-polygon-color');
  textColor = style.getPropertyValue('--fabrication-text-color');
  if (settings.renderFabrication) {
    drawBgLayer(
      "fabrication", canvasdict.fab, canvasdict.layer,
      canvasdict.transform.s * canvasdict.transform.zoom,
      edgeColor, polygonColor, textColor);
  }
}

function prepareCanvas(canvas, flip, transform) {
  var ctx = canvas.getContext("2d");
  ctx.setTransform(1, 0, 0, 1, 0, 0);
  var fontsize = 1.55;
  ctx.scale(transform.zoom, transform.zoom);
  ctx.translate(transform.panx, transform.pany);
  if (flip) {
    ctx.scale(-1, 1);
  }
  ctx.translate(transform.x, transform.y);
  ctx.rotate(deg2rad(settings.boardRotation));
  ctx.scale(transform.s, transform.s);
}

function prepareLayer(canvasdict) {
  var flip = (canvasdict.layer == "B");
  for (var c of ["bg", "fab", "silk", "highlight"]) {
    prepareCanvas(canvasdict[c], flip, canvasdict.transform);
  }
}

function rotateVector(v, angle) {
  angle = deg2rad(angle);
  return [
    v[0] * Math.cos(angle) - v[1] * Math.sin(angle),
    v[0] * Math.sin(angle) + v[1] * Math.cos(angle)
  ];
}

function applyRotation(bbox) {
  var corners = [
    [bbox.minx, bbox.miny],
    [bbox.minx, bbox.maxy],
    [bbox.maxx, bbox.miny],
    [bbox.maxx, bbox.maxy],
  ];
  corners = corners.map((v) => rotateVector(v, settings.boardRotation));
  return {
    minx: corners.reduce((a, v) => Math.min(a, v[0]), Infinity),
    miny: corners.reduce((a, v) => Math.min(a, v[1]), Infinity),
    maxx: corners.reduce((a, v) => Math.max(a, v[0]), -Infinity),
    maxy: corners.reduce((a, v) => Math.max(a, v[1]), -Infinity),
  }
}

function recalcLayerScale(layerdict, width, height) {
  var bbox = applyRotation(pcbdata.edges_bbox);
  var scalefactor = 0.98 * Math.min(
    width / (bbox.maxx - bbox.minx),
    height / (bbox.maxy - bbox.miny)
  );
  if (scalefactor < 0.1) {
    scalefactor = 1;
  }
  layerdict.transform.s = scalefactor;
  var flip = (layerdict.layer == "B");
  if (flip) {
    layerdict.transform.x = -((bbox.maxx + bbox.minx) * scalefactor + width) * 0.5;
  } else {
    layerdict.transform.x = -((bbox.maxx + bbox.minx) * scalefactor - width) * 0.5;
  }
  layerdict.transform.y = -((bbox.maxy + bbox.miny) * scalefactor - height) * 0.5;
  for (var c of ["bg", "fab", "silk", "highlight"]) {
    canvas = layerdict[c];
    canvas.width = width;
    canvas.height = height;
    canvas.style.width = (width / devicePixelRatio) + "px";
    canvas.style.height = (height / devicePixelRatio) + "px";
  }
}

function redrawCanvas(layerdict) {
  prepareLayer(layerdict);
  drawBackground(layerdict);
  drawHighlightsOnLayer(layerdict);
}

function resizeCanvas(layerdict) {
  var canvasdivid = {
    "F": "frontcanvas",
    "B": "backcanvas"
  } [layerdict.layer];
  var width = document.getElementById(canvasdivid).clientWidth * devicePixelRatio;
  var height = document.getElementById(canvasdivid).clientHeight * devicePixelRatio;
  recalcLayerScale(layerdict, width, height);
  redrawCanvas(layerdict);
}

function resizeAll() {
  resizeCanvas(allcanvas.front);
  resizeCanvas(allcanvas.back);
}

function pointWithinDistanceToSegment(x, y, x1, y1, x2, y2, d) {
  var A = x - x1;
  var B = y - y1;
  var C = x2 - x1;
  var D = y2 - y1;

  var dot = A * C + B * D;
  var len_sq = C * C + D * D;
  var dx, dy;
  if (len_sq == 0) {
    // start and end of the segment coincide
    dx = x - x1;
    dy = y - y1;
  } else {
    var param = dot / len_sq;
    var xx, yy;
    if (param < 0) {
      xx = x1;
      yy = y1;
    } else if (param > 1) {
      xx = x2;
      yy = y2;
    } else {
      xx = x1 + param * C;
      yy = y1 + param * D;
    }
    dx = x - xx;
    dy = y - yy;
  }
  return dx * dx + dy * dy <= d * d;
}

function pointWithinPad(x, y, pad) {
  var v = [x - pad.pos[0], y - pad.pos[1]];
  v = rotateVector(v, -pad.angle);
  if (pad.offset) {
    v[0] -= pad.offset[0];
    v[1] -= pad.offset[1];
  }
  return emptyContext2d.isPointInPath(getCachedPadPath(pad), ...v);
}

function netHitScan(layer, x, y) {
  // Check track segments
  if (settings.renderTracks && pcbdata.tracks) {
    for(var track of pcbdata.tracks[layer]) {
      if (pointWithinDistanceToSegment(x, y, ...track.start, ...track.end, track.width / 2)) {
        return track.net;
      }
    }
  }
  // Check pads
  if (settings.renderPads) {
    for (var mod of pcbdata.modules) {
      for(var pad of mod.pads) {
        if (pad.layers.includes(layer) && pointWithinPad(x, y, pad)) {
          return pad.net;
        }
      }
    }
  }
  return null;
}

function pointWithinModuleBbox(x, y, bbox) {
  var v = [x - bbox.pos[0], y - bbox.pos[1]];
  v = rotateVector(v, bbox.angle);
  return bbox.relpos[0] <= v[0] && v[0] <= bbox.relpos[0] + bbox.size[0] &&
         bbox.relpos[1] <= v[1] && v[1] <= bbox.relpos[1] + bbox.size[1];
}

function bboxHitScan(layer, x, y) {
  var result = [];
  for (var i = 0; i < pcbdata.modules.length; i++) {
    var module = pcbdata.modules[i];
    if (module.layer == layer) {
      if (pointWithinModuleBbox(x, y, module.bbox)) {
        result.push(i);
      }
    }
  }
  return result;
}

function handlePointerDown(e, layerdict) {
  if (e.button != 0 && e.button != 1) {
    return;
  }
  e.preventDefault();
  e.stopPropagation();

  if (!e.hasOwnProperty("offsetX")) {
    // The polyfill doesn't set this properly
    e.offsetX = e.pageX - e.currentTarget.offsetLeft;
    e.offsetY = e.pageY - e.currentTarget.offsetTop;
  }

  layerdict.pointerStates[e.pointerId] = {
    distanceTravelled: 0,
    lastX: e.offsetX,
    lastY: e.offsetY,
    downTime: Date.now(),
  };
}

function handleMouseClick(e, layerdict) {
  if (!e.hasOwnProperty("offsetX")) {
    // The polyfill doesn't set this properly
    e.offsetX = e.pageX - e.currentTarget.offsetLeft;
    e.offsetY = e.pageY - e.currentTarget.offsetTop;
  }

  var x = e.offsetX;
  var y = e.offsetY;
  var t = layerdict.transform;
  if (layerdict.layer == "B") {
    x = (devicePixelRatio * x / t.zoom - t.panx + t.x) / -t.s;
  } else {
    x = (devicePixelRatio * x / t.zoom - t.panx - t.x) / t.s;
  }
  y = (devicePixelRatio * y / t.zoom - t.y - t.pany) / t.s;
  var v = rotateVector([x, y], -settings.boardRotation);
  if ("nets" in pcbdata) {
    var net = netHitScan(layerdict.layer, ...v);
    if (net !== highlightedNet) {
      netClicked(net);
    }
  }
  if (highlightedNet === null) {
    var modules = bboxHitScan(layerdict.layer, ...v);
    if (modules.length > 0) {
      modulesClicked(modules);
    }
  }
}

function handlePointerLeave(e, layerdict) {
  e.preventDefault();
  e.stopPropagation();

  if (!settings.redrawOnDrag) {
    redrawCanvas(layerdict);
  }

  delete layerdict.pointerStates[e.pointerId];
}

function resetTransform(layerdict) {
  layerdict.transform.panx = 0;
  layerdict.transform.pany = 0;
  layerdict.transform.zoom = 1;
  redrawCanvas(layerdict);
}

function handlePointerUp(e, layerdict) {
  if (!e.hasOwnProperty("offsetX")) {
    // The polyfill doesn't set this properly
    e.offsetX = e.pageX - e.currentTarget.offsetLeft;
    e.offsetY = e.pageY - e.currentTarget.offsetTop;
  }

  e.preventDefault();
  e.stopPropagation();

  if (e.button == 2) {
    // Reset pan and zoom on right click.
    resetTransform(layerdict);
    layerdict.anotherPointerTapped = false;
    return;
  }

  // We haven't necessarily had a pointermove event since the interaction started, so make sure we update this now
  var ptr = layerdict.pointerStates[e.pointerId];
  ptr.distanceTravelled += Math.abs(e.offsetX - ptr.lastX) + Math.abs(e.offsetY - ptr.lastY);

  if (e.button == 0 && ptr.distanceTravelled < 10 && Date.now() - ptr.downTime <= 500) {
    if (Object.keys(layerdict.pointerStates).length == 1) {
      if (layerdict.anotherPointerTapped) {
        // This is the second pointer coming off of a two-finger tap
        resetTransform(layerdict);
      } else {
        // This is just a regular tap
        handleMouseClick(e, layerdict);
      }
      layerdict.anotherPointerTapped = false;
    } else {
      // This is the first finger coming off of what could become a two-finger tap
      layerdict.anotherPointerTapped = true;
    }
  } else {
    if (!settings.redrawOnDrag) {
      redrawCanvas(layerdict);
    }
    layerdict.anotherPointerTapped = false;
  }

  delete layerdict.pointerStates[e.pointerId];
}

function handlePointerMove(e, layerdict) {
  if (!layerdict.pointerStates.hasOwnProperty(e.pointerId)) {
    return;
  }
  e.preventDefault();
  e.stopPropagation();

  if (!e.hasOwnProperty("offsetX")) {
    // The polyfill doesn't set this properly
    e.offsetX = e.pageX - e.currentTarget.offsetLeft;
    e.offsetY = e.pageY - e.currentTarget.offsetTop;
  }

  var thisPtr = layerdict.pointerStates[e.pointerId];

  var dx = e.offsetX - thisPtr.lastX;
  var dy = e.offsetY - thisPtr.lastY;

  // If this number is low on pointer up, we count the action as a click
  thisPtr.distanceTravelled += Math.abs(dx) + Math.abs(dy);

  if (Object.keys(layerdict.pointerStates).length == 1) {
    // This is a simple drag
    layerdict.transform.panx += devicePixelRatio * dx / layerdict.transform.zoom;
    layerdict.transform.pany += devicePixelRatio * dy / layerdict.transform.zoom;
  } else if (Object.keys(layerdict.pointerStates).length == 2) {
    var otherPtr = Object.values(layerdict.pointerStates).filter((ptr) => ptr != thisPtr)[0];

    var oldDist = Math.sqrt(Math.pow(thisPtr.lastX - otherPtr.lastX, 2) + Math.pow(thisPtr.lastY - otherPtr.lastY, 2));
    var newDist = Math.sqrt(Math.pow(e.offsetX - otherPtr.lastX, 2)     + Math.pow(e.offsetY - otherPtr.lastY, 2));

    var scaleFactor = newDist/oldDist;

    if (scaleFactor != NaN) {
      layerdict.transform.zoom *= scaleFactor;

      var zoomd = (1 - scaleFactor) / layerdict.transform.zoom;
      layerdict.transform.panx += devicePixelRatio * otherPtr.lastX * zoomd;
      layerdict.transform.pany += devicePixelRatio * otherPtr.lastY * zoomd;
    }
  }

  thisPtr.lastX = e.offsetX;
  thisPtr.lastY = e.offsetY;

  if (settings.redrawOnDrag) {
    redrawCanvas(layerdict);
  }
}

function handleMouseWheel(e, layerdict) {
  e.preventDefault();
  e.stopPropagation();
  var t = layerdict.transform;
  var wheeldelta = e.deltaY;
  if (e.deltaMode == 1) {
    // FF only, scroll by lines
    wheeldelta *= 30;
  } else if (e.deltaMode == 2) {
    wheeldelta *= 300;
  }
  var m = Math.pow(1.1, -wheeldelta / 40);
  // Limit amount of zoom per tick.
  if (m > 2) {
    m = 2;
  } else if (m < 0.5) {
    m = 0.5;
  }
  t.zoom *= m;
  var zoomd = (1 - m) / t.zoom;
  t.panx += devicePixelRatio * e.offsetX * zoomd;
  t.pany += devicePixelRatio * e.offsetY * zoomd;
  redrawCanvas(layerdict);
}

function addMouseHandlers(div, layerdict) {
  div.addEventListener("pointerdown", function(e) {
    handlePointerDown(e, layerdict);
  });
  div.addEventListener("pointermove", function(e) {
    handlePointerMove(e, layerdict);
  });
  div.addEventListener("pointerup", function(e) {
    handlePointerUp(e, layerdict);
  });
  var pointerleave = function(e) {
    handlePointerLeave(e, layerdict);
  }
  div.addEventListener("pointercancel", pointerleave);
  div.addEventListener("pointerleave", pointerleave);
  div.addEventListener("pointerout", pointerleave);

  div.onwheel = function(e) {
    handleMouseWheel(e, layerdict);
  }
  for (var element of [div, layerdict.bg, layerdict.fab, layerdict.silk, layerdict.highlight]) {
    element.addEventListener("contextmenu", function(e) {
      e.preventDefault();
    }, false);
  }
}

function setRedrawOnDrag(value) {
  settings.redrawOnDrag = value;
  writeStorage("redrawOnDrag", value);
}

function setBoardRotation(value) {
  settings.boardRotation = value * 5;
  writeStorage("boardRotation", settings.boardRotation);
  document.getElementById("rotationDegree").textContent = settings.boardRotation;
  resizeAll();
}

function initRender() {
  allcanvas = {
    front: {
      transform: {
        x: 0,
        y: 0,
        s: 1,
        panx: 0,
        pany: 0,
        zoom: 1,
      },
      pointerStates: {},
      anotherPointerTapped: false,
      bg: document.getElementById("F_bg"),
      fab: document.getElementById("F_fab"),
      silk: document.getElementById("F_slk"),
      highlight: document.getElementById("F_hl"),
      layer: "F",
    },
    back: {
      transform: {
        x: 0,
        y: 0,
        s: 1,
        panx: 0,
        pany: 0,
        zoom: 1,
      },
      pointerStates: {},
      anotherPointerTapped: false,
      bg: document.getElementById("B_bg"),
      fab: document.getElementById("B_fab"),
      silk: document.getElementById("B_slk"),
      highlight: document.getElementById("B_hl"),
      layer: "B",
    }
  };
  addMouseHandlers(document.getElementById("frontcanvas"), allcanvas.front);
  addMouseHandlers(document.getElementById("backcanvas"), allcanvas.back);
}

///////////////////////////////////////////////

///////////////////////////////////////////////
/* DOM manipulation and misc code */

var bomsplit;
var canvassplit;
var initDone = false;
var bomSortFunction = null;
var currentSortColumn = null;
var currentSortOrder = null;
var currentHighlightedRowId;
var highlightHandlers = [];
var moduleIndexToHandler = {};
var netsToHandler = {};
var highlightedModules = [];
var highlightedNet = null;
var lastClicked;

function dbg(html) {
  dbgdiv.innerHTML = html;
}

function redrawIfInitDone() {
  if (initDone) {
    redrawCanvas(allcanvas.front);
    redrawCanvas(allcanvas.back);
  }
}

function padsVisible(value) {
  writeStorage("padsVisible", value);
  settings.renderPads = value;
  redrawIfInitDone();
}

function referencesVisible(value) {
  writeStorage("referencesVisible", value);
  settings.renderReferences = value;
  redrawIfInitDone();
}

function valuesVisible(value) {
  writeStorage("valuesVisible", value);
  settings.renderValues = value;
  redrawIfInitDone();
}

function tracksVisible(value) {
  writeStorage("tracksVisible", value);
  settings.renderTracks = value;
  redrawIfInitDone();
}

function zonesVisible(value) {
  writeStorage("zonesVisible", value);
  settings.renderZones = value;
  redrawIfInitDone();
}

function dnpOutline(value) {
  writeStorage("dnpOutline", value);
  settings.renderDnpOutline = value;
  redrawIfInitDone();
}

function setDarkMode(value) {
  if (value) {
    topmostdiv.classList.add("dark");
  } else {
    topmostdiv.classList.remove("dark");
  }
  writeStorage("darkmode", value);
  settings.darkMode = value;
  redrawIfInitDone();
}

function setFullscreen(value) {
  if (value) {
    document.documentElement.requestFullscreen();
  } else {
    document.exitFullscreen();
  }
}

function fabricationVisible(value) {
  writeStorage("fabricationVisible", value);
  settings.renderFabrication = value;
  redrawIfInitDone();
}

function silkscreenVisible(value) {
  writeStorage("silkscreenVisible", value);
  settings.renderSilkscreen = value;
  redrawIfInitDone();
}

function setHighlightPin1(value) {
  writeStorage("highlightpin1", value);
  settings.highlightpin1 = value;
  redrawIfInitDone();
}

function getStoredCheckboxRefs(checkbox) {
  function convert(ref) {
    var intref = parseInt(ref);
    if (isNaN(intref)) {
      for (var i = 0; i < pcbdata.modules.length; i++) {
        if (pcbdata.modules[i].ref == ref) {
          return i;
        }
      }
      return -1;
    } else {
      return intref;
    }
  }
  if (!(checkbox in settings.checkboxStoredRefs)) {
    var val = readStorage("checkbox_" + checkbox);
    settings.checkboxStoredRefs[checkbox] = val ? val : "";
  }
  if (!settings.checkboxStoredRefs[checkbox]) {
    return new Set();
  } else {
    return new Set(settings.checkboxStoredRefs[checkbox].split(",").map(r => convert(r)).filter(a => a >= 0));
  }
}

function getCheckboxState(checkbox, references) {
  var storedRefsSet = getStoredCheckboxRefs(checkbox);
  var currentRefsSet = new Set(references.map(r => r[1]));
  // Get difference of current - stored
  var difference = new Set(currentRefsSet);
  for (ref of storedRefsSet) {
    difference.delete(ref);
  }
  if (difference.size == 0) {
    // All the current refs are stored
    return "checked";
  } else if (difference.size == currentRefsSet.size) {
    // None of the current refs are stored
    return "unchecked";
  } else {
    // Some of the refs are stored
    return "indeterminate";
  }
}

function setBomCheckboxState(checkbox, element, references) {
  var state = getCheckboxState(checkbox, references);
  element.checked = (state == "checked");
  element.indeterminate = (state == "indeterminate");
}

function createCheckboxChangeHandler(checkbox, references, row) {
  return function() {
    refsSet = getStoredCheckboxRefs(checkbox);
    var darkenWhenChecked = settings.darkenWhenChecked == checkbox;
    eventArgs = {
      checkbox: checkbox,
      refs: references,
    }
    if (this.checked) {
      // checkbox ticked
      for (var ref of references) {
        refsSet.add(ref[1]);
      }
      if (darkenWhenChecked) {
        row.classList.add("checked");
      }
      eventArgs.state = 'checked';
    } else {
      // checkbox unticked
      for (var ref of references) {
        refsSet.delete(ref[1]);
      }
      if (darkenWhenChecked) {
        row.classList.remove("checked");
      }
      eventArgs.state = 'unchecked';
    }
    settings.checkboxStoredRefs[checkbox] = [...refsSet].join(",");
    writeStorage("checkbox_" + checkbox, settings.checkboxStoredRefs[checkbox]);
    updateCheckboxStats(checkbox);
    EventHandler.emitEvent(IBOM_EVENT_TYPES.CHECKBOX_CHANGE_EVENT, eventArgs);
  }
}

function clearHighlightedModules() {
  if (currentHighlightedRowId) {
    document.getElementById(currentHighlightedRowId).classList.remove("highlighted");
    currentHighlightedRowId = null;
    highlightedModules = [];
    highlightedNet = null;
  }
}

function createRowHighlightHandler(rowid, refs, net) {
  return function() {
    if (currentHighlightedRowId) {
      if (currentHighlightedRowId == rowid) {
        return;
      }
      document.getElementById(currentHighlightedRowId).classList.remove("highlighted");
    }
    document.getElementById(rowid).classList.add("highlighted");
    currentHighlightedRowId = rowid;
    highlightedModules = refs ? refs.map(r => r[1]) : [];
    highlightedNet = net;
    drawHighlights();
    EventHandler.emitEvent(
      IBOM_EVENT_TYPES.HIGHLIGHT_EVENT,
      {
        rowid: rowid,
        refs: refs,
        net: net
      });
  }
}

function entryMatches(entry) {
  if (settings.bommode == "netlist") {
    // entry is just a net name
    return entry.toLowerCase().indexOf(filter) >= 0;
  }
  // check refs
  for (var ref of entry[3]) {
    if (ref[0].toLowerCase().indexOf(filter) >= 0) {
      return true;
    }
  }
  // check extra fields
  for (var i in config.extra_fields) {
    if (entry[4][i].toLowerCase().indexOf(filter) >= 0) {
      return true;
    }
  }
  // check value
  if (entry[1].toLowerCase().indexOf(filter) >= 0) {
    return true;
  }
  // check footprint
  if (entry[2].toLowerCase().indexOf(filter) >= 0) {
    return true;
  }
  return false;
}

function findRefInEntry(entry) {
  return entry[3].filter(r => r[0].toLowerCase() == reflookup);
}

function highlightFilter(s) {
  if (!filter) {
    return s;
  }
  var parts = s.toLowerCase().split(filter);
  if (parts.length == 1) {
    return s;
  }
  var r = "";
  var pos = 0;
  for (var i in parts) {
    if (i > 0) {
      r += '<mark class="highlight">' +
        s.substring(pos, pos + filter.length) +
        '</mark>';
      pos += filter.length;
    }
    r += s.substring(pos, pos + parts[i].length);
    pos += parts[i].length;
  }
  return r;
}

function checkboxSetUnsetAllHandler(checkboxname) {
  return function() {
    var checkboxnum = 0;
    while (checkboxnum < settings.checkboxes.length &&
      settings.checkboxes[checkboxnum].toLowerCase() != checkboxname.toLowerCase()) {
      checkboxnum++;
    }
    if (checkboxnum >= settings.checkboxes.length) {
      return;
    }
    var allset = true;
    var checkbox;
    var row;
    for (row of bombody.childNodes) {
      checkbox = row.childNodes[checkboxnum + 1].childNodes[0];
      if (!checkbox.checked || checkbox.indeterminate) {
        allset = false;
        break;
      }
    }
    for (row of bombody.childNodes) {
      checkbox = row.childNodes[checkboxnum + 1].childNodes[0];
      checkbox.checked = !allset;
      checkbox.indeterminate = false;
      checkbox.onchange();
    }
  }
}

function createColumnHeader(name, cls, comparator) {
  var th = document.createElement("TH");
  th.innerHTML = name;
  th.classList.add(cls);
  th.style.cursor = "pointer";
  var span = document.createElement("SPAN");
  span.classList.add("sortmark");
  span.classList.add("none");
  th.appendChild(span);
  th.onclick = function() {
    if (currentSortColumn && this !== currentSortColumn) {
      // Currently sorted by another column
      currentSortColumn.childNodes[1].classList.remove(currentSortOrder);
      currentSortColumn.childNodes[1].classList.add("none");
      currentSortColumn = null;
      currentSortOrder = null;
    }
    if (currentSortColumn && this === currentSortColumn) {
      // Already sorted by this column
      if (currentSortOrder == "asc") {
        // Sort by this column, descending order
        bomSortFunction = function(a, b) {
          return -comparator(a, b);
        }
        currentSortColumn.childNodes[1].classList.remove("asc");
        currentSortColumn.childNodes[1].classList.add("desc");
        currentSortOrder = "desc";
      } else {
        // Unsort
        bomSortFunction = null;
        currentSortColumn.childNodes[1].classList.remove("desc");
        currentSortColumn.childNodes[1].classList.add("none");
        currentSortColumn = null;
        currentSortOrder = null;
      }
    } else {
      // Sort by this column, ascending order
      bomSortFunction = comparator;
      currentSortColumn = this;
      currentSortColumn.childNodes[1].classList.remove("none");
      currentSortColumn.childNodes[1].classList.add("asc");
      currentSortOrder = "asc";
    }
    populateBomBody();
  }
  return th;
}

function populateBomHeader() {
  while (bomhead.firstChild) {
    bomhead.removeChild(bomhead.firstChild);
  }
  var tr = document.createElement("TR");
  var th = document.createElement("TH");
  th.classList.add("numCol");
  tr.appendChild(th);
  var checkboxCompareClosure = function(checkbox) {
    return (a, b) => {
      var stateA = getCheckboxState(checkbox, a[3]);
      var stateB = getCheckboxState(checkbox, b[3]);
      if (stateA > stateB) return -1;
      if (stateA < stateB) return 1;
      return 0;
    }
  }
  if (settings.bommode == "netlist") {
    th = createColumnHeader("Net name", "bom-netname", (a, b) => {
      if (a > b) return -1;
      if (a < b) return 1;
      return 0;
    });
    tr.appendChild(th);
  } else {
    for (var checkbox of settings.checkboxes) {
      th = createColumnHeader(
        checkbox, "bom-checkbox", checkboxCompareClosure(checkbox));
      th.onclick = fancyDblClickHandler(
        th, th.onclick.bind(th), checkboxSetUnsetAllHandler(checkbox));
      tr.appendChild(th);
    }
    tr.appendChild(createColumnHeader("References", "References", (a, b) => {
      var i = 0;
      while (i < a[3].length && i < b[3].length) {
        if (a[3][i] != b[3][i]) return a[3][i] > b[3][i] ? 1 : -1;
        i++;
      }
      return a[3].length - b[3].length;
    }));
    // Extra fields
    if (config.extra_fields.length > 0) {
      var extraFieldCompareClosure = function(fieldIndex) {
        return (a, b) => {
          var fa = a[4][fieldIndex];
          var fb = b[4][fieldIndex];
          if (fa != fb) return fa > fb ? 1 : -1;
          else return 0;
        }
      }
      for (var i in config.extra_fields) {
        tr.appendChild(createColumnHeader(
          config.extra_fields[i], "extra", extraFieldCompareClosure(i)));
      }
    }
    tr.appendChild(createColumnHeader("Value", "Value", (a, b) => {
      return valueCompare(a[5], b[5], a[1], b[1]);
    }));
    tr.appendChild(createColumnHeader("Footprint", "Footprint", (a, b) => {
      if (a[2] != b[2]) return a[2] > b[2] ? 1 : -1;
      else return 0;
    }));
    if (settings.bommode == "grouped") {
      tr.appendChild(createColumnHeader("Quantity", "Quantity", (a, b) => {
        return a[3].length - b[3].length;
      }));
    }
  }
  bomhead.appendChild(tr);
}

function populateBomBody() {
  while (bom.firstChild) {
    bom.removeChild(bom.firstChild);
  }
  highlightHandlers = [];
  moduleIndexToHandler = {};
  netsToHandler = {};
  currentHighlightedRowId = null;
  var first = true;
  if (settings.bommode == "netlist") {
    bomtable = pcbdata.nets.slice();
  } else {
    switch (settings.canvaslayout) {
      case 'F':
        bomtable = pcbdata.bom.F.slice();
        break;
      case 'FB':
        bomtable = pcbdata.bom.both.slice();
        break;
      case 'B':
        bomtable = pcbdata.bom.B.slice();
        break;
    }
    if (settings.bommode == "ungrouped") {
      // expand bom table
      expandedTable = []
      for (var bomentry of bomtable) {
        for (var ref of bomentry[3]) {
          expandedTable.push([1, bomentry[1], bomentry[2], [ref], bomentry[4], bomentry[5]]);
        }
      }
      bomtable = expandedTable;
    }
  }
  if (bomSortFunction) {
    bomtable = bomtable.sort(bomSortFunction);
  }
  for (var i in bomtable) {
    var bomentry = bomtable[i];
    if (filter && !entryMatches(bomentry)) {
      continue;
    }
    var references = null;
    var netname = null;
    var tr = document.createElement("TR");
    var td = document.createElement("TD");
    var rownum = +i + 1;
    tr.id = "bomrow" + rownum;
    td.textContent = rownum;
    tr.appendChild(td);
    if (settings.bommode == "netlist") {
      netname = bomentry;
      td = document.createElement("TD");
      td.innerHTML = highlightFilter(netname ? netname : "&lt;no net&gt;");
      tr.appendChild(td);
    } else {
      if (reflookup) {
        references = findRefInEntry(bomentry);
        if (references.length == 0) {
          continue;
        }
      } else {
        references = bomentry[3];
      }
      // Checkboxes
      for (var checkbox of settings.checkboxes) {
        if (checkbox) {
          td = document.createElement("TD");
          var input = document.createElement("input");
          input.type = "checkbox";
          input.onchange = createCheckboxChangeHandler(checkbox, references, tr);
          setBomCheckboxState(checkbox, input, references);
          if (input.checked && settings.darkenWhenChecked == checkbox) {
            tr.classList.add("checked");
          }
          td.appendChild(input);
          tr.appendChild(td);
        }
      }
      // References
      td = document.createElement("TD");
      td.innerHTML = highlightFilter(references.map(r => r[0]).join(", "));
      tr.appendChild(td);
      // Extra fields
      for (var i in config.extra_fields) {
        td = document.createElement("TD");
        td.innerHTML = highlightFilter(bomentry[4][i]);
        tr.appendChild(td);
      }
      // Value
      td = document.createElement("TD");
      td.innerHTML = highlightFilter(bomentry[1]);
      tr.appendChild(td);
      // Footprint
      td = document.createElement("TD");
      td.innerHTML = highlightFilter(bomentry[2]);
      tr.appendChild(td);
      if (settings.bommode == "grouped") {
        // Quantity
        td = document.createElement("TD");
        td.textContent = bomentry[3].length;
        tr.appendChild(td);
      }
    }
    bom.appendChild(tr);
    var handler = createRowHighlightHandler(tr.id, references, netname);
    tr.onmousemove = handler;
    highlightHandlers.push({
      id: tr.id,
      handler: handler,
    });
    if (references !== null) {
      for (var refIndex of references.map(r => r[1])) {
        moduleIndexToHandler[refIndex] = handler;
      }
    }
    if (netname !== null) {
      netsToHandler[netname] = handler;
    }
    if ((filter || reflookup) && first) {
      handler();
      first = false;
    }
  }
  EventHandler.emitEvent(
    IBOM_EVENT_TYPES.BOM_BODY_CHANGE_EVENT,
    {
      filter: filter,
      reflookup: reflookup,
      checkboxes: settings.checkboxes,
      bommode: settings.bommode,
    });
}

function highlightPreviousRow() {
  if (!currentHighlightedRowId) {
    highlightHandlers[highlightHandlers.length - 1].handler();
  } else {
    if (highlightHandlers.length > 1 &&
      highlightHandlers[0].id == currentHighlightedRowId) {
      highlightHandlers[highlightHandlers.length - 1].handler();
    } else {
      for (var i = 0; i < highlightHandlers.length - 1; i++) {
        if (highlightHandlers[i + 1].id == currentHighlightedRowId) {
          highlightHandlers[i].handler();
          break;
        }
      }
    }
  }
  smoothScrollToRow(currentHighlightedRowId);
}

function highlightNextRow() {
  if (!currentHighlightedRowId) {
    highlightHandlers[0].handler();
  } else {
    if (highlightHandlers.length > 1 &&
      highlightHandlers[highlightHandlers.length - 1].id == currentHighlightedRowId) {
      highlightHandlers[0].handler();
    } else {
      for (var i = 1; i < highlightHandlers.length; i++) {
        if (highlightHandlers[i - 1].id == currentHighlightedRowId) {
          highlightHandlers[i].handler();
          break;
        }
      }
    }
  }
  smoothScrollToRow(currentHighlightedRowId);
}

function populateBomTable() {
  populateBomHeader();
  populateBomBody();
}

function modulesClicked(moduleIndexes) {
  var lastClickedIndex = moduleIndexes.indexOf(lastClicked);
  for (var i = 1; i <= moduleIndexes.length; i++) {
    var refIndex = moduleIndexes[(lastClickedIndex + i) % moduleIndexes.length];
    if (refIndex in moduleIndexToHandler) {
      lastClicked = refIndex;
      moduleIndexToHandler[refIndex]();
      smoothScrollToRow(currentHighlightedRowId);
      break;
    }
  }
}

function netClicked(net) {
  if (net in netsToHandler) {
    netsToHandler[net]();
    smoothScrollToRow(currentHighlightedRowId);
  } else {
    clearHighlightedModules();
    highlightedNet = net;
    drawHighlights();
  }
}

function updateFilter(input) {
  filter = input.toLowerCase();
  populateBomTable();
}

function updateRefLookup(input) {
  reflookup = input.toLowerCase();
  populateBomTable();
}

function changeCanvasLayout(layout) {
  document.getElementById("fl-btn").classList.remove("depressed");
  document.getElementById("fb-btn").classList.remove("depressed");
  document.getElementById("bl-btn").classList.remove("depressed");
  switch (layout) {
    case 'F':
      document.getElementById("fl-btn").classList.add("depressed");
      if (settings.bomlayout != "bom-only") {
        canvassplit.collapse(1);
      }
      break;
    case 'B':
      document.getElementById("bl-btn").classList.add("depressed");
      if (settings.bomlayout != "bom-only") {
        canvassplit.collapse(0);
      }
      break;
    default:
      document.getElementById("fb-btn").classList.add("depressed");
      if (settings.bomlayout != "bom-only") {
        canvassplit.setSizes([50, 50]);
      }
  }
  settings.canvaslayout = layout;
  writeStorage("canvaslayout", layout);
  resizeAll();
  changeBomMode(settings.bommode);
}

function populateMetadata() {
  document.getElementById("title").innerHTML = pcbdata.metadata.title;
  document.getElementById("revision").innerHTML = "Rev: " + pcbdata.metadata.revision;
  document.getElementById("company").innerHTML = pcbdata.metadata.company;
  document.getElementById("filedate").innerHTML = pcbdata.metadata.date;
  if (pcbdata.metadata.title != "") {
    document.title = pcbdata.metadata.title + " BOM";
  }
  // Calculate board stats
  var fp_f = 0, fp_b = 0, pads_f = 0, pads_b = 0, pads_th = 0;
  for (var i = 0; i < pcbdata.modules.length; i++) {
    if (pcbdata.bom.skipped.includes(i)) continue;
    var mod = pcbdata.modules[i];
    if (mod.layer == "F") {
      fp_f++;
    } else {
      fp_b++;
    }
    for (var pad of mod.pads) {
      if (pad.type == "th") {
        pads_th++;
      } else {
        if (pad.layers.includes("F")) {
          pads_f++;
        }
        if (pad.layers.includes("B")) {
          pads_b++;
        }
      }
    }
  }
  document.getElementById("stats-components-front").innerHTML = fp_f;
  document.getElementById("stats-components-back").innerHTML = fp_b;
  document.getElementById("stats-components-total").innerHTML = fp_f + fp_b;
  document.getElementById("stats-groups-front").innerHTML = pcbdata.bom.F.length;
  document.getElementById("stats-groups-back").innerHTML = pcbdata.bom.B.length;
  document.getElementById("stats-groups-total").innerHTML = pcbdata.bom.both.length;
  document.getElementById("stats-smd-pads-front").innerHTML = pads_f;
  document.getElementById("stats-smd-pads-back").innerHTML = pads_b;
  document.getElementById("stats-smd-pads-total").innerHTML = pads_f + pads_b;
  document.getElementById("stats-th-pads").innerHTML = pads_th;
  // Update version string
  document.getElementById("github-link").innerHTML = "InteractiveHtmlBom&nbsp;" +
    /^v\d+\.\d+/.exec(pcbdata.ibom_version)[0];
}

function changeBomLayout(layout) {
  document.getElementById("bom-btn").classList.remove("depressed");
  document.getElementById("lr-btn").classList.remove("depressed");
  document.getElementById("tb-btn").classList.remove("depressed");
  switch (layout) {
    case 'bom-only':
      document.getElementById("bom-btn").classList.add("depressed");
      if (bomsplit) {
        bomsplit.destroy();
        bomsplit = null;
        canvassplit.destroy();
        canvassplit = null;
      }
      document.getElementById("frontcanvas").style.display = "none";
      document.getElementById("backcanvas").style.display = "none";
      document.getElementById("bot").style.height = "";
      break;
    case 'top-bottom':
      document.getElementById("tb-btn").classList.add("depressed");
      document.getElementById("frontcanvas").style.display = "";
      document.getElementById("backcanvas").style.display = "";
      document.getElementById("bot").style.height = "calc(100% - 80px)";
      document.getElementById("bomdiv").classList.remove("split-horizontal");
      document.getElementById("canvasdiv").classList.remove("split-horizontal");
      document.getElementById("frontcanvas").classList.add("split-horizontal");
      document.getElementById("backcanvas").classList.add("split-horizontal");
      if (bomsplit) {
        bomsplit.destroy();
        bomsplit = null;
        canvassplit.destroy();
        canvassplit = null;
      }
      bomsplit = Split(['#bomdiv', '#canvasdiv'], {
        sizes: [50, 50],
        onDragEnd: resizeAll,
        direction: "vertical",
        gutterSize: 5
      });
      canvassplit = Split(['#frontcanvas', '#backcanvas'], {
        sizes: [50, 50],
        gutterSize: 5,
        onDragEnd: resizeAll
      });
      break;
    case 'left-right':
      document.getElementById("lr-btn").classList.add("depressed");
      document.getElementById("frontcanvas").style.display = "";
      document.getElementById("backcanvas").style.display = "";
      document.getElementById("bot").style.height = "calc(100% - 80px)";
      document.getElementById("bomdiv").classList.add("split-horizontal");
      document.getElementById("canvasdiv").classList.add("split-horizontal");
      document.getElementById("frontcanvas").classList.remove("split-horizontal");
      document.getElementById("backcanvas").classList.remove("split-horizontal");
      if (bomsplit) {
        bomsplit.destroy();
        bomsplit = null;
        canvassplit.destroy();
        canvassplit = null;
      }
      bomsplit = Split(['#bomdiv', '#canvasdiv'], {
        sizes: [50, 50],
        onDragEnd: resizeAll,
        gutterSize: 5
      });
      canvassplit = Split(['#frontcanvas', '#backcanvas'], {
        sizes: [50, 50],
        gutterSize: 5,
        direction: "vertical",
        onDragEnd: resizeAll
      });
  }
  settings.bomlayout = layout;
  writeStorage("bomlayout", layout);
  changeCanvasLayout(settings.canvaslayout);
}

function changeBomMode(mode) {
  document.getElementById("bom-grouped-btn").classList.remove("depressed");
  document.getElementById("bom-ungrouped-btn").classList.remove("depressed");
  document.getElementById("bom-netlist-btn").classList.remove("depressed");
  switch (mode) {
    case 'grouped':
      document.getElementById("bom-grouped-btn").classList.add("depressed");
      break;
    case 'ungrouped':
      document.getElementById("bom-ungrouped-btn").classList.add("depressed");
      break;
    case 'netlist':
      document.getElementById("bom-netlist-btn").classList.add("depressed");
  }
  writeStorage("bommode", mode);
  if (mode != settings.bommode) {
    settings.bommode = mode;
    bomSortFunction = null;
    currentSortColumn = null;
    currentSortOrder = null;
    clearHighlightedModules();
  }
  populateBomTable();
}

function focusFilterField() {
  focusInputField(document.getElementById("filter"));
}

function focusRefLookupField() {
  focusInputField(document.getElementById("reflookup"));
}

function toggleBomCheckbox(bomrowid, checkboxnum) {
  if (!bomrowid || checkboxnum > settings.checkboxes.length) {
    return;
  }
  var bomrow = document.getElementById(bomrowid);
  var checkbox = bomrow.childNodes[checkboxnum].childNodes[0];
  checkbox.checked = !checkbox.checked;
  checkbox.indeterminate = false;
  checkbox.onchange();
}

function checkBomCheckbox(bomrowid, checkboxname) {
  var checkboxnum = 0;
  while (checkboxnum < settings.checkboxes.length &&
    settings.checkboxes[checkboxnum].toLowerCase() != checkboxname.toLowerCase()) {
    checkboxnum++;
  }
  if (!bomrowid || checkboxnum >= settings.checkboxes.length) {
    return;
  }
  var bomrow = document.getElementById(bomrowid);
  var checkbox = bomrow.childNodes[checkboxnum + 1].childNodes[0];
  checkbox.checked = true;
  checkbox.indeterminate = false;
  checkbox.onchange();
}

function setBomCheckboxes(value) {
  writeStorage("bomCheckboxes", value);
  settings.checkboxes = value.split(",").filter((e) => e);
  prepCheckboxes();
  populateBomTable();
  populateDarkenWhenCheckedOptions();
}

function setDarkenWhenChecked(value) {
  writeStorage("darkenWhenChecked", value);
  settings.darkenWhenChecked = value;
  populateBomTable();
}

function prepCheckboxes() {
  var table = document.getElementById("checkbox-stats");
  while (table.childElementCount > 1) {
    table.removeChild(table.lastChild);
  }
  if (settings.checkboxes.length) {
    table.style.display = "";
  } else {
    table.style.display = "none";
  }
  for (var checkbox of settings.checkboxes) {
    var tr = document.createElement("TR");
    var td = document.createElement("TD");
    td.innerHTML = checkbox;
    tr.appendChild(td);
    td = document.createElement("TD");
    td.id = "checkbox-stats-" + checkbox;
    var progressbar = document.createElement("div");
    progressbar.classList.add("bar");
    td.appendChild(progressbar);
    var text = document.createElement("div");
    text.classList.add("text");
    td.appendChild(text);
    tr.appendChild(td);
    table.appendChild(tr);
    updateCheckboxStats(checkbox);
  }
}

function populateDarkenWhenCheckedOptions() {
  var container = document.getElementById("darkenWhenCheckedContainer");

  if (settings.checkboxes.length == 0) {
    container.parentElement.style.display = "none";
    return;
  }

  container.innerHTML = '';
  container.parentElement.style.display = "inline-block";

  function createOption(name, displayName) {
    var id = "darkenWhenChecked-" + name;

    var div = document.createElement("div");
    div.classList.add("radio-container");

    var input = document.createElement("input");
    input.type = "radio";
    input.name = "darkenWhenChecked";
    input.value = name;
    input.id = id;
    input.onchange = () => setDarkenWhenChecked(name);
    div.appendChild(input);

    // Preserve the selected element when the checkboxes change
    if (name == settings.darkenWhenChecked) {
      input.checked = true;
    }

    var label = document.createElement("label");
    label.innerHTML = displayName;
    label.htmlFor = id;
    div.appendChild(label);

    container.appendChild(div);
  }
  createOption("", "None");
  for (var checkbox of settings.checkboxes) {
    createOption(checkbox, checkbox);
  }
}

function updateCheckboxStats(checkbox) {
  var checked = getStoredCheckboxRefs(checkbox).size;
  var total = pcbdata.modules.length - pcbdata.bom.skipped.length;
  var percent = checked * 100.0 / total;
  var td = document.getElementById("checkbox-stats-" + checkbox);
  td.firstChild.style.width = percent + "%";
  td.lastChild.innerHTML = checked + "/" + total + " (" + Math.round(percent) + "%)";
}

document.onkeydown = function(e) {
  switch (e.key) {
    case "n":
      if (document.activeElement.type == "text") {
        return;
      }
      if (currentHighlightedRowId !== null) {
        checkBomCheckbox(currentHighlightedRowId, "placed");
        highlightNextRow();
        e.preventDefault();
      }
      break;
    case "ArrowUp":
      highlightPreviousRow();
      e.preventDefault();
      break;
    case "ArrowDown":
      highlightNextRow();
      e.preventDefault();
      break;
    default:
      break;
  }
  if (e.altKey) {
    switch (e.key) {
      case "f":
        focusFilterField();
        e.preventDefault();
        break;
      case "r":
        focusRefLookupField();
        e.preventDefault();
        break;
      case "z":
        changeBomLayout("bom-only");
        e.preventDefault();
        break;
      case "x":
        changeBomLayout("left-right");
        e.preventDefault();
        break;
      case "c":
        changeBomLayout("top-bottom");
        e.preventDefault();
        break;
      case "v":
        changeCanvasLayout("F");
        e.preventDefault();
        break;
      case "b":
        changeCanvasLayout("FB");
        e.preventDefault();
        break;
      case "n":
        changeCanvasLayout("B");
        e.preventDefault();
        break;
      default:
        break;
    }
    if (e.key >= '1' && e.key <= '9') {
      toggleBomCheckbox(currentHighlightedRowId, parseInt(e.key));
    }
  }
}

function hideNetlistButton() {
  document.getElementById("bom-ungrouped-btn").classList.remove("middle-button");
  document.getElementById("bom-ungrouped-btn").classList.add("right-most-button");
  document.getElementById("bom-netlist-btn").style.display = "none";
}

window.onload = function(e) {
  initUtils();
  initRender();
  initStorage();
  initDefaults();
  cleanGutters();
  populateMetadata();
  dbgdiv = document.getElementById("dbg");
  bom = document.getElementById("bombody");
  bomhead = document.getElementById("bomhead");
  filter = "";
  reflookup = "";
  if (!("nets" in pcbdata)) {
    hideNetlistButton();
  }
  initDone = true;
  prepCheckboxes();
  // Triggers render
  changeBomLayout(settings.bomlayout);

  // Users may leave fullscreen without touching the checkbox. Uncheck.
  document.addEventListener('fullscreenchange', () => {
    if (!document.fullscreenElement)
      document.getElementById('fullscreenCheckbox').checked = false;
  });
}

window.onresize = resizeAll;
window.matchMedia("print").addListener(resizeAll);

///////////////////////////////////////////////

///////////////////////////////////////////////

///////////////////////////////////////////////
  </script>
</head>

<body>

<div id="topmostdiv" class="topmostdiv">
  <div id="top">
    <div style="float: right; height: 100%;">
      <div class="hideonprint menu" style="float: right; top: 8px;">
        <button class="menubtn"></button>
        <div class="menu-content">
          <label class="menu-label menu-label-top" style="width: calc(50% - 18px)">
            <input id="darkmodeCheckbox" type="checkbox" onchange="setDarkMode(this.checked)">
            Dark mode
          </label><!-- This comment eats space! All of it!
          --><label class="menu-label menu-label-top" style="width: calc(50% - 17px); border-left: 0;">
            <input id="fullscreenCheckbox" type="checkbox" onchange="setFullscreen(this.checked)">
            Full Screen
          </label>
          <label class="menu-label" style="width: calc(50% - 18px)">
            <input id="fabricationCheckbox" type="checkbox" checked onchange="fabricationVisible(this.checked)">
            Fab layer
          </label><!-- This comment eats space! All of it!
          --><label class="menu-label" style="width: calc(50% - 17px); border-left: 0;">
            <input id="silkscreenCheckbox" type="checkbox" checked onchange="silkscreenVisible(this.checked)">
            Silkscreen
          </label>
          <label class="menu-label" style="width: calc(50% - 18px)">
            <input id="referencesCheckbox" type="checkbox" checked onchange="referencesVisible(this.checked)">
            References
          </label><!-- This comment eats space! All of it!
          --><label class="menu-label" style="width: calc(50% - 17px); border-left: 0;">
            <input id="valuesCheckbox" type="checkbox" checked onchange="valuesVisible(this.checked)">
            Values
          </label>
          <div id="tracksAndZonesCheckboxes">
            <label class="menu-label" style="width: calc(50% - 18px)">
              <input id="tracksCheckbox" type="checkbox" checked onchange="tracksVisible(this.checked)">
              Tracks
            </label><!-- This comment eats space! All of it!
            --><label class="menu-label" style="width: calc(50% - 17px); border-left: 0;">
              <input id="zonesCheckbox" type="checkbox" checked onchange="zonesVisible(this.checked)">
              Zones
            </label>
          </div>
          <label class="menu-label" style="width: calc(50% - 18px)">
            <input id="padsCheckbox" type="checkbox" checked onchange="padsVisible(this.checked)">
            Pads
          </label><!-- This comment eats space! All of it!
          --><label class="menu-label" style="width: calc(50% - 17px); border-left: 0;">
            <input id="dnpOutlineCheckbox" type="checkbox" checked onchange="dnpOutline(this.checked)">
            DNP outlined
          </label>
          <label class="menu-label">
            <input id="highlightpin1Checkbox" type="checkbox" onchange="setHighlightPin1(this.checked)">
            Highlight first pin
          </label>
          <label class="menu-label">
            <input id="dragCheckbox" type="checkbox" checked onchange="setRedrawOnDrag(this.checked)">
            Continuous redraw on drag
          </label>
          <label class="menu-label">
            <span>Board rotation</span>
            <span style="float: right"><span id="rotationDegree">0</span>&#176;</span>
            <input id="boardRotation" type="range" min="-36" max="36" value="0" class="slider" oninput="setBoardRotation(this.value)">
          </label>
          <label class="menu-label">
            <div style="margin-left: 5px">Bom checkboxes</div>
            <input id="bomCheckboxes" class="menu-textbox" type=text
                   oninput="setBomCheckboxes(this.value)">
          </label>
          <label class="menu-label">
            <div style="margin-left: 5px">Darken when checked</div>
            <div id="darkenWhenCheckedContainer"></div>
          </label>
          <label class="menu-label">
            <span class="shameless-plug">
              <span>Created using</span>
              <a id="github-link" target="blank" href="https://github.com/openscopeproject/InteractiveHtmlBom">InteractiveHtmlBom</a>
            </span>
          </label>
        </div>
      </div>
      <div class="button-container hideonprint"
           style="float: right; position: relative; top: 8px">
        <button id="fl-btn" class="left-most-button" onclick="changeCanvasLayout('F')"
                title="Front only">F
        </button>
        <button id="fb-btn" class="middle-button" onclick="changeCanvasLayout('FB')"
                title="Front and Back">FB
        </button>
        <button id="bl-btn" class="right-most-button" onclick="changeCanvasLayout('B')"
                title="Back only">B
        </button>
      </div>
      <div class="button-container hideonprint"
           style="float: right; position: relative; top: 8px">
        <button id="bom-btn" class="left-most-button" onclick="changeBomLayout('bom-only')"
                title="BOM only"></button>
        <button id="lr-btn" class="middle-button" onclick="changeBomLayout('left-right')"
                title="BOM left, drawings right"></button>
        <button id="tb-btn" class="right-most-button" onclick="changeBomLayout('top-bottom')"
                title="BOM top, drawings bot"></button>
      </div>
      <div class="button-container hideonprint"
           style="float: right; position: relative; top: 8px">
        <button id="bom-grouped-btn" class="left-most-button" onclick="changeBomMode('grouped')"
                title="Grouped BOM"></button>
        <button id="bom-ungrouped-btn" class="middle-button" onclick="changeBomMode('ungrouped')"
                title="Ungrouped BOM"></button>
        <button id="bom-netlist-btn" class="right-most-button" onclick="changeBomMode('netlist')"
                title="Netlist"></button>
      </div>
      <div class="hideonprint menu" style="float: right; top: 8px;">
        <button class="statsbtn"></button>
        <div class="menu-content">
          <table class="stats">
            <tbody>
              <tr>
                <td width="40%">Board stats</td>
                <td>Front</td>
                <td>Back</td>
                <td>Total</td>
              </tr>
              <tr>
                <td>Components</td>
                <td id="stats-components-front">~</td>
                <td id="stats-components-back">~</td>
                <td id="stats-components-total">~</td>
              </tr>
              <tr>
                <td>Groups</td>
                <td id="stats-groups-front">~</td>
                <td id="stats-groups-back">~</td>
                <td id="stats-groups-total">~</td>
              </tr>
              <tr>
                <td>SMD pads</td>
                <td id="stats-smd-pads-front">~</td>
                <td id="stats-smd-pads-back">~</td>
                <td id="stats-smd-pads-total">~</td>
              </tr>
              <tr>
                <td>TH pads</td>
                <td colspan=3 id="stats-th-pads">~</td>
              </tr>
            </tbody>
          </table>
          <table class="stats">
            <col width="40%"/><col />
            <tbody id="checkbox-stats">
              <tr>
                <td colspan=2 style="border-top: 0">Checkboxes</td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
      <div class="hideonprint menu" style="float: right; top: 8px;">
        <button class="iobtn"></button>
        <div class="menu-content">
          <div class="menu-label menu-label-top">
            <div style="margin-left: 5px;">Save board image</div>
            <div class="flexbox">
              <input id="render-save-width" class="menu-textbox" type="text" value="1000" placeholder="Width"
                  style="flex-grow: 1; width: 50px;" oninput="validateSaveImgDimension(this)">
              <span>X</span>
              <input id="render-save-height" class="menu-textbox" type="text" value="1000" placeholder="Height"
                  style="flex-grow: 1; width: 50px;" oninput="validateSaveImgDimension(this)">
            </div>
            <label>
              <input id="render-save-transparent" type="checkbox">
              Transparent background
            </label>
            <div class="flexbox">
              <button class="savebtn" onclick="saveImage('F')">Front</button>
              <button class="savebtn" onclick="saveImage('B')">Back</button>
            </div>
          </div>
          <div class="menu-label">
            <span style="margin-left: 5px;">Config and checkbox state</span>
            <div class="flexbox">
              <button class="savebtn" onclick="saveSettings()">Export</button>
              <button class="savebtn" onclick="loadSettings()">Import</button>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div id="fileinfodiv" style="overflow: auto;">
      <table class="fileinfo">
        <tbody>
          <tr>
            <td id="title" class="title" style="width: 70%">
              Title
            </td>
            <td id="revision" class="title" style="width: 30%">
              Revision
            </td>
          </tr>
          <tr>
            <td id="company">
              Company
            </td>
            <td id="filedate">
              Date
            </td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>
  <div id="bot" class="split" style="height: calc(100% - 80px)">
    <div id="bomdiv" class="split split-horizontal">
      <div style="width: 100%">
        <input id="reflookup" class="textbox searchbox reflookup hideonprint" type="text" placeholder="Ref lookup"
               oninput="updateRefLookup(this.value)">
        <input id="filter" class="textbox searchbox filter hideonprint" type="text" placeholder="Filter"
               oninput="updateFilter(this.value)">
        <div class="button-container hideonprint" style="float: left; margin: 0;">
          <button id="copy" title="Copy bom table to clipboard"
               onclick="copyToClipboard()"></button>
        </div>
      </div>
      <div id="dbg"></div>
      <table class="bom">
        <thead id="bomhead">
        </thead>
        <tbody id="bombody">
        </tbody>
      </table>
    </div>
    <div id="canvasdiv" class="split split-horizontal">
      <div id="frontcanvas" class="split" touch-action="none" style="overflow: hidden">
        <div style="position: relative; width: 100%; height: 100%;">
          <canvas id="F_bg" style="position: absolute; left: 0; top: 0; z-index: 0;"></canvas>
          <canvas id="F_fab" style="position: absolute; left: 0; top: 0; z-index: 1;"></canvas>
          <canvas id="F_slk" style="position: absolute; left: 0; top: 0; z-index: 2;"></canvas>
          <canvas id="F_hl" style="position: absolute; left: 0; top: 0; z-index: 3;"></canvas>
        </div>
      </div>
      <div id="backcanvas" class="split" touch-action="none" style="overflow: hidden">
        <div style="position: relative; width: 100%; height: 100%;">
          <canvas id="B_bg" style="position: absolute; left: 0; top: 0; z-index: 0;"></canvas>
          <canvas id="B_fab" style="position: absolute; left: 0; top: 0; z-index: 1;"></canvas>
          <canvas id="B_slk" style="position: absolute; left: 0; top: 0; z-index: 2;"></canvas>
          <canvas id="B_hl" style="position: absolute; left: 0; top: 0; z-index: 3;"></canvas>
        </div>
      </div>
    </div>
  </div>
</div>

</body>

</html>
